How to Gambas 3 Building GUI Applications

How to
Gambas 3
Building GUI
Applications
version 0.0.1 Pre-release 1
Main Author:
Willy Raets (The Netherlands)
<willy@development.earthshipbelgium.be>
Version:
0.0.1 Pre-release 1 (2013-09-29)
Contributing author:
Illustrations:
Sholzy (United Stated), Illustrations 173
Willy Raets (The Netherlands), Illustrations 1-172, 174-178
Proofreaders:
Alain J. Baudrez (Belgium)
Ammar Ali Kurd (Yemen)
Jim Cook (United States)
Netizen1993 (United States)
Instruction and example testing
Alain J. Baudrez (Belgium)
Ammar Ali Kurd (Yemen)
Jim Cook (United States)
Netizen1993 (United States)
Advisors:
Alain J. Baudrez (Belgium)
Ian Roper (Australia)
How to Gambas 3 – Building GUI Applications (this work) is licensed by Willy J.L. Raets under the Creative
Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License
In short meaning that everyone can share and read this work for free, as is. Commercial use is not allowed, neither is changing the work. You need to attribute in the manner required by the licensor (see
below). Check the full license text for a detailed explanation. For conditions of use prohibited by this
license, contact the licensor.
THIS WORK IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL"
OR "LICENSE"). THIS WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE
OF THIS WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
UNLESS OTHERWISE MUTUALLY AGREED BY THE PARTIES IN WRITING, LICENSOR OFFERS THIS WORK
AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THIS WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE,
MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR
NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES,
SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
For full license text visit: http://creativecommons.org/licenses/by-nc-nd/3.0/legalcode
Attribution is required as follows:
'How to Gambas 3 – Building GUI Applications' by Willy Raets (http://howtogambas.org)
Table of Contents
1 HOW THIS GOT STARTED.........................................................................................1
2 FOREWORD................................................................................................................2
3 BEFORE YOU GET STARTED....................................................................................3
3.1 BACKGROUND INFORMATION......................................................................................................3
3.2 EXAMPLE CODE.....................................................................................................................3
3.3 GOOD PRACTICE...................................................................................................................3
3.4 TERMINAL.............................................................................................................................3
3.5 WARNING.............................................................................................................................4
3.6 CONTROLS AND MENUS...........................................................................................................4
4 INTRODUCTION..........................................................................................................5
4.1 WHAT IS GAMBAS?................................................................................................................5
5 SOME GOOD PRACTICES.........................................................................................6
5.1 FOLDER ORGANISATION............................................................................................................6
5.1.1 Development folder........................................................................................................ 6
5.1.2 Distributions folder......................................................................................................... 7
5.2 PROJECT ORGANISATION..........................................................................................................9
5.3 ORGANISING YOUR CODE.........................................................................................................9
5.3.1 Commenting your code................................................................................................ 10
5.3.2 Clear choices for names.............................................................................................. 11
5.3.3 Indenting code............................................................................................................. 12
5.3.4 Eliminate repeating code.............................................................................................. 13
6 A FIRST GUI APPLICATION: TEXTPLAY.................................................................14
6.1 WHAT WILL BE DONE IN THIS CHAPTER......................................................................................14
6.2 STARTING A NEW PROJECT.....................................................................................................14
6.3 CREATING A FORM AND CONTROLS...........................................................................................18
6.3.1 Placing controls on a form............................................................................................ 19
6.3.2 A closer look at the controls......................................................................................... 22
6.4 CODING, TESTING, CODING, TESTING.........................................................................................24
6.4.1 Objects, properties, events and methods.....................................................................24
6.4.2 Write some code and test (round 1).............................................................................24
6.4.3 Code some improvements and test (round 2)..............................................................27
7 EXTENDING APPLICATION TEXTPLAY..................................................................30
7.1 WHAT WILL BE DONE IN THIS CHAPTER......................................................................................30
7.2 OPEN AN EXISTING PROJECT...................................................................................................30
7.3 MODIFY MAIN FORM AND ADD CONTROLS....................................................................................31
7.3.1 Copy controls on the form............................................................................................ 33
7.3.2 A closer look at the controls......................................................................................... 34
7.4 CODING, TESTING AND ADAPTING.............................................................................................37
7.4.1 Coding and testing (round 1)........................................................................................ 37
7.4.2 Adapting, coding and testing (round 2).........................................................................38
7.4.3 Adding new controls, code and test (round 3)..............................................................41
7.4.4 Add some last controls, code and test (round 4)..........................................................46
7.5 A LAST REVIEW OF THE APPLICATION.........................................................................................53
7.5.1 Do you need a button Show?.......................................................................................53
7.5.2 Could iSwitch format be more clear?...........................................................................53
7.5.3 Should the button Add be enabled if no Add is checked?............................................54
7.5.4 Should the button Clear be enabled if there is nothing to clear?..................................54
7.6 ANSWERS TO THE LAST REVIEW ...............................................................................................54
7.6.1 Do you need a button Show?.......................................................................................54
7.6.2 Could iSwitch format be more clear?...........................................................................56
7.6.3 Should the button Add be enabled if no Add is checked?............................................56
7.6.4 Should the button Clear be enabled if there is nothing to clear?..................................57
8 YOUR SECOND APPLICATION: TEXTPLAYT(W)O.................................................59
8.1 WHAT WILL BE DONE IN THIS CHAPTER......................................................................................59
8.2 START A NEW PROJECT AND DESIGN THE FIRST FORM...................................................................59
8.3 PLAYING WITH TEXT THE OTHER WAY AROUND.............................................................................60
8.3.1 Some first coding to split the text.................................................................................60
8.3.2 Determine the number of splits....................................................................................64
8.4 SEARCH FOR TEXT...............................................................................................................68
8.4.1 Make a new form......................................................................................................... 68
8.4.2 Make FrmSearchReplace open from btnSearch on FrmMain......................................70
8.4.3 Project intermezzo: Form class interaction explained..................................................71
8.4.4 Back on track to code a Public method on FrmMain....................................................73
8.4.5 Lets search some string............................................................................................... 74
8.5 SEARCH AND REPLACE TEXT...................................................................................................76
8.5.1 Prepare the forms for Search and Replace..................................................................76
8.5.2 Making FrmSearchReplace appear depending on selection in FrmMain.....................77
8.5.3 Replace searched strings............................................................................................ 80
9 YOUR THIRD APPLICATION: NUMPLAY.................................................................82
9.1 WHAT WILL BE DONE IN THIS CHAPTER......................................................................................82
9.2 START A NEW PROJECT AND DESIGN A FORM...............................................................................82
9.3 DOING THE MATHS................................................................................................................83
9.3.1 Analyse the needs and determine a strategy...............................................................84
9.3.2 Implement error handling............................................................................................. 88
9.4 WORKING WITH NUMBERS IN TEXT VARIABLES AND TEXT CONTROLS..................................................90
9.4.1 Simple beginnings........................................................................................................ 91
9.4.2 Next challenge............................................................................................................. 92
9.5 HOW ABOUT DATE AND TIME...................................................................................................95
9.5.1 Adding some code....................................................................................................... 96
9.5.2 More date and time...................................................................................................... 97
9.6 ANOTHER APPROACH, ENUMERATE............................................................................................99
9.6.1 iSwitch enumerated..................................................................................................... 99
10 YOUR FOURTH APPLICATION: IMAGEPLAY....................................................102
10.1 WHAT WILL BE DONE IN THIS CHAPTER..................................................................................102
10.2 START A NEW PROJECT AND DESIGN A FORM..........................................................................102
10.3 LET ME SEE SOME IMAGES.................................................................................................103
10.3.1 Making some images............................................................................................... 103
10.3.2 Make the images appear.......................................................................................... 104
10.3.3 Code the labels........................................................................................................ 107
10.4 LOADING IMAGES USING CODE.............................................................................................111
10.4.1 The mission............................................................................................................. 112
10.4.2 Make the labels work again......................................................................................113
11 YOUR FIFTH APPLICATION: SIMPLETEXTEDITOR..........................................115
11.1 WHAT WILL BE DONE IN THIS CHAPTER..................................................................................115
11.2 START A NEW PROJECT AND DESIGN A FORM..........................................................................115
11.3 MAKING A MENU..............................................................................................................116
11.3.1 Coding the menu entry New.....................................................................................118
11.3.2 Adding Icon and keyboard shortcut to menu entry New...........................................119
11.4 SAVING YOUR FIRST TEXT FILE.............................................................................................120
11.4.1 On a mission............................................................................................................ 120
11.4.2 Lets save some text................................................................................................. 121
11.4.3 Get name and path to save to..................................................................................123
11.5 OPENING YOUR FIRST TEXT FILE..........................................................................................126
11.5.1 Code for opening..................................................................................................... 126
11.5.2 Make sure an opened file can be saved...................................................................127
11.6 LITTLE INTERMEZZO..........................................................................................................128
11.7 BACK ON TRACK FOR SAVE AS...........................................................................................132
11.7.1 Code Save As menu item......................................................................................... 132
11.7.2 Simplifying the code for saving................................................................................133
11.8 PUTTING THE DOTS ON THE I...............................................................................................134
11.8.1 Offer to save when closed after editing text file........................................................135
11.8.2 Bug!! What bug?!..................................................................................................... 138
11.8.3 Resizing the application window..............................................................................141
11.8.4 Adding a ToolBar...................................................................................................... 143
11.8.5 Reordering menu items............................................................................................ 147
11.8.6 Adding new menus................................................................................................... 148
11.8.7 Application caption................................................................................................... 150
11.9 A LAST NOTE ON CODE ORGANISATION...................................................................................153
12
END NOTE FOR PRE-RELEASE 1......................................................................155
13
APPENDICES............................................................................................................ I
14
BIBLIOGRAPHY....................................................................................................XII
List of Illustrations
Illustration 1: Organisation of 'Development' folder...........................................................6
Illustration 2: Organisation of 'Distributions' folder.............................................................8
Illustration 3: Application folder with version folders containing the packages...................9
Illustration 4: Organisation of a project folder in the Gambas IDE.....................................9
Illustration 5: Gambas 3.4.1 opening screen...................................................................14
Illustration 6: 'New project' screen step 1. Select the type of application........................15
Illustration 7: 'New project' screen step 2. Select the folder for the new project..............15
Illustration 8: Create a new folder for Learning projects..................................................16
Illustration 9: Select the folder 'Gambas3-Learning'........................................................16
Illustration 10: 'New project' screen step 3. Name the project folder and project ...........17
Illustration 11: Message when project has been created successfully............................17
Illustration 12: New project 'TextPlay' opened in Gambas 3 IDE.....................................18
Illustration 13: FMain in Sources folder of the project.....................................................18
Illustration 14: Empty form in IDE....................................................................................19
Illustration 15: Label icon in ToolBox...............................................................................20
Illustration 16: Label control drawn on the form..............................................................20
Illustration 17: TextBox icon in ToolBox...........................................................................20
Illustration 18: TextBox control drawn on the form...........................................................21
Illustration 19: Button icon in ToolBox..............................................................................21
Illustration 20: Two button controls drawn on the form....................................................21
Illustration 21: Select Alignment of the Label control.......................................................22
Illustration 22: Label1 aligned right..................................................................................23
Illustration 23: Label1 Text property changed..................................................................23
Illustration 24: Controls after changing the properties.....................................................23
Illustration 25: Select Event Click for button control........................................................25
Illustration 26: FMain.class..............................................................................................25
Illustration 27: Menu Debug -> Run to test the application..............................................26
Illustration 28: Application running with message shown.................................................27
Illustration 29: Message when no name entered.............................................................29
Illustration 30: Message when name entered..................................................................29
Illustration 31: Gambas welcome screen 'Recent projects'.............................................30
Illustration 32: Mouse appearance will change where the pointer is................................31
Illustration 33: Form dragged wider and Label and TextArea selected............................31
Illustration 34: Drag the buttons to the bottom of the form..............................................32
Illustration 35: Result after adapting the form..................................................................32
Illustration 36: Pasted controls on the form.....................................................................33
Illustration 37: Controls dragged to the spot you need them...........................................33
Illustration 38: Result after copy/pasting all needed controls...........................................33
Illustration 39: Label1 after changing the Text property...................................................34
Illustration 40: Name properties of both TextBoxes changed..........................................34
Illustration 41: Main form after the changes in the exercise............................................35
Illustration 42: Names of buttons changed in Fmain.class as well..................................36
Illustration 43: Main form after adding two more controls................................................36
Illustration 44: Result after clicking button Add................................................................37
Illustration 45: Hierarchy of the controls on main form....................................................38
Illustration 46: Hierarchy after adaptation........................................................................38
Illustration 47: Set selected controls NoTabFocus property to True................................39
Illustration 48: Clicking Add without filling in a name.......................................................40
Illustration 49: Three CheckBoxes and three RadioButtons............................................41
Illustration 50: All CheckBoxes selected, only one RadioButton......................................41
Illustration 51: Result of 2 lines selected.........................................................................43
Illustration 52: Clicked button Add with only Name selected...........................................45
Illustration 53: New controls added and adapted............................................................46
Illustration 54: Testing the new code...............................................................................49
Illustration 55: Selecting RadioButton 'Show' deselects RadioButton '1 line'...................50
Illustration 56: ToolBox tab Container showing Frame....................................................50
Illustration 57: Frame Show placed on form....................................................................51
Illustration 58: RadioButtons pasted into Frame Show....................................................51
Illustration 59: All RadioButtons placed in their Frames..................................................52
Illustration 60: RadioButtons show working as supposed................................................52
Illustration 61: No button Show but still doing the same job............................................55
Illustration 62: Main form in IDE design mode.................................................................60
Illustration 63: Main form when run from IDE..................................................................60
Illustration 64: Text splitted on the dot (.).........................................................................62
Illustration 65: Result of splitting on \n.............................................................................63
Illustration 66: Renewed result of splitting on "\n"...........................................................64
Illustration 67: Result of splitting on "\n" showing 2 lines.................................................65
Illustration 68: Split for 4 lines.........................................................................................67
Illustration 69: Next a split for 1 line (other lines are now cleared)..................................68
Illustration 70: Ad a new form to the project....................................................................68
Illustration 71: Dialog to name the form...........................................................................69
Illustration 72: FrmSearchReplace with controls placed..................................................69
Illustration 73: FrmSearchReplace opened from btnSearch............................................71
Illustration 74: Running btnSplit code from btnSearch on another form..........................72
Illustration 75: Interaction between methods in different form classes............................73
Illustration 76: Search string passed as argument of a Public method............................74
Illustration 77: Seems like search performs as expected................................................76
Illustration 78: Replace TextBox and Button added to FrmSearchReplace.....................76
Illustration 79: FrmSearch property Enabled set to true on FrmMain..............................77
Illustration 80: Search shown when search selected.......................................................79
Illustration 81: Search and Replace shown when search/replace selected.....................79
Illustration 82: Search still works well..............................................................................81
Illustration 83: Replace does a good job as well.............................................................81
Illustration 84: FrmMain after placing all controls............................................................83
Illustration 85: FrmMain when run...................................................................................83
Illustration 86: lblOperator shows selected Operator.......................................................84
Illustration 87: Console output in IDE..............................................................................86
Illustration 88: Calculating values 10 and 2.....................................................................87
Illustration 89: Division by zero error...............................................................................87
Illustration 90: Error 26 returned.....................................................................................89
Illustration 91: Division by zero now handled properly.....................................................90
Illustration 92: FrmMain after adding some controls........................................................90
Illustration 93: Calculating the text seems to work..........................................................91
Illustration 94: Division by zero taken care off.................................................................94
Illustration 95: Unknown operator taken care off.............................................................94
Illustration 96: Some extra controls added to play with date and time.............................96
Illustration 97: After Date is selected the other controls are updated accordingly...........97
Illustration 98: Timer object can be found in the toolbox on tab 'Special'.........................98
Illustration 99: Timer object can be anywhere on the form..............................................98
Illustration 100: Every second the tbxDate1 and 2 change their content.........................99
Illustration 101: Controls placed on FrmMain................................................................102
Illustration 102: Create a new folder 'Images' in the project Data folder........................103
Illustration 103: Made some modern art image.............................................................103
Illustration 104: Image copied, edited and saved. That makes two works of art............104
Illustration 105: Make panel appear..............................................................................104
Illustration 106: Opening the 'Select a picture' form......................................................105
Illustration 107: Image 'MyImage.png' in PictureBox picOne.........................................105
Illustration 108: Both images in their PictureBox...........................................................105
Illustration 109: Running ImagePlay for the first time....................................................106
Illustration 110: Clicking the button switches the images between the PictureBoxes....107
Illustration 111: Labels now showing the image dimensions.........................................108
Illustration 112: Two more png images made in the editor............................................108
Illustration 113: Running the application with the new images......................................109
Illustration 114: Images switch but labels show wrong dimensions...............................109
Illustration 115: All works as expected..........................................................................110
Illustration 116: All new controls placed on FrmMain.....................................................111
Illustration 117: Project folder structure.........................................................................112
Illustration 118: Auto-complete function of IDE will recognise the path.........................112
Illustration 119: The pictures seem to load but the labels aren't adapted......................113
Illustration 120: Loading images now adapts the Labels accordingly............................114
Illustration 121: FrmMain after placing the control.........................................................115
Illustration 122: Select Menu editor...............................................................................116
Illustration 123: Adding 9 menu entries in the Menu editor............................................116
Illustration 124: Indent the menu entry..........................................................................117
Illustration 125: The end result of editing the menu entries...........................................117
Illustration 126: There is a menu File on FrmMain in IDE..............................................118
Illustration 127: Before and after clicking menu File -> New.........................................118
Illustration 128: Set the keyboard shortcut for menu New.............................................119
Illustration 129: Selecting the new icon.........................................................................119
Illustration 130: File menu with the newly added icon for New......................................120
Illustration 131: Make sure your menu entry for Save has an icon and keyboard entry 121
Illustration 132: Ready to save my first file....................................................................124
Illustration 133: Dialog Save text file.............................................................................125
Illustration 134: Notification that the file has been saved...............................................125
Illustration 135: Dialog Open text file.............................................................................127
Illustration 136: Saved the changes to the text file........................................................128
Illustration 137: Part of the File menu disabled as should be........................................129
Illustration 138: Oops.., no way to save a new text file..................................................130
Illustration 139: The end result of some polishing of the File menu...............................131
Illustration 140: Save As dialog.....................................................................................132
Illustration 141: Notification that the file was saved using a new name.........................133
Illustration 142: The auto-help will know your new routine............................................134
Illustration 143: Closing after editing gives a warning and option to save.....................138
Illustration 144: Changed shown in Console means Change event is triggered............139
Illustration 145: Dragging the window bigger doesn't change the TextArea...................141
Illustration 146: Set the Arrangement property of FrmMain...........................................141
Illustration 147: The TextArea now does resize with the window...................................142
Illustration 148: Arrangement set to Fill does the job.....................................................142
Illustration 149: HBox is found on the Tab Container.....................................................143
Illustration 150: All new controls in place.......................................................................143
Illustration 151: A strange looking form, but New button works.....................................144
Illustration 152: Set txaMain property Expand to True...................................................144
Illustration 153: Make sure all ToolButtons are inside the HBox....................................145
Illustration 154: A running resizeable SimpeTextEditor with Toolbar..............................146
Illustration 155: Toolbar with property Spacing set to False..........................................147
Illustration 156: Toolbar with property Spacing set to True............................................147
Illustration 157: A click on Move Up button brings the item higher................................147
Illustration 158: Added menus with ToolBar menu item set checked.............................148
Illustration 159: A new menu View Toolbar....................................................................148
Illustration 160: With ToolBar checked..........................................................................149
Illustration 161: With Toolbar unchecked.......................................................................150
Illustration 162: Menu Help -> About shows some info on the application.....................150
Illustration 163: 'New text document' added to application caption...............................151
Illustration 164: Caption showing the name of the opened text file...............................152
Illustration 165: Save the new text document................................................................153
Illustration 166: After saving the caption changed.........................................................153
Illustration 167: FrmMain.class code organised in certain order...................................154
Illustration 168: Gambas website - Menu Mailing lists/Forums..........................................II
Illustration 169: Gambas website - Overview Mailing Lists & Forums...............................II
Illustration 170: Subscribe to the Gambas-user mailinglist...............................................III
Illustration 171: Gambas mailing list Forum.....................................................................IV
Illustration 172: Gambas IDE - System information form..................................................V
Illustration 173: White Island and GambasForum (circled the login and join)..................VI
Illustration 174: Search, Post since last visit and Topics with unread posts....................VII
Illustration 175: Gambas based projects with sub forum 'How to Gambas 3'................VIII
Illustration 176: Sub forums and topics of 'How to Gambas 3' forum...............................IX
Illustration 177: Topics in sub forum 'Building GUI Applications'......................................IX
Illustration 178: Gambas Learning - a learning aid for Gambas........................................X
Appendices
Appendix I: Linux command reference...............................................................................I
Appendix II: Subscribe to the official Gambas mailing lists/Forum....................................II
Appendix III: Reporting problems on the official Gambas mailing list................................V
Appendix IV: White Island Software and GambasForum quick tour.................................VI
Appendix V: Getting help with the 'How to Gambas 3' guides.......................................VIII
Appendix VI: Application Gambas Learning – a learning aid for Gambas.........................X
Appendix VII: Overview of the 'How To Gambas 3' guides..............................................XI
1. How this got started
1 How this got started
Somewhere in 2009 I finally decided to install Linux on one of my systems. After my first initial
exploring of the operating systems, the provided applications and more a new world opened
up to me.
I soon discovered the stability and power of Linux and moreover the power of an open source
community. So after exploring Linux a while I felt like programming. Since most of my last and
current work involved programming client interfaces for databases in VB, I went looking for a
good alternative on the Linux platform.
And then I found Gambas (at that time in version 2) and loved it right from the start. It's ease
of use and logic in syntax surprised me, captured me and never let me go. Since that day all
my coding that is not job related is done in Gambas1.
For me, as a professional application developer , finding my way in Gambas wasn't always
that easy. Documentation is very basic and explains the syntax of the language with little or
no examples. There are some guides out there, but they are scares. Nevertheless I manage
because of my years of experience with programming.
I can see how a new programmer might find it hard to understand how Gambas and Linux
work, then leave in disappointment and frustration.
Back in the old days, about every computer had a programming language and manual delivered along with it. A lot of young people in those days learned programming this way and
Gambas is an excellent tool to do just that on a Linux platform.
As it is based on BASIC (Beginners All purpose Symbolic Instruction Code), a language
many in the eighties learned themselves, it is perfect for a beginner to learn programming.
Although a lot has changed since Basic saw birth, it still is the same language, but much
more powerful because of Gambas providing an environment to make event driven GUI
(Graphical User Interface) applications. It's possible to build easy GUI applications doing
simple things in no time.
And that is what this series aims at. People new to programming and wanting to learn the
skills. So that is what will be covered in a simple manner, so any newbie can learn. Every part
of the series will cover a specific topic. And in time you will have all the basic skills to build
your own applications in Gambas 3.
Enjoy...
Willy Raets,
Main author,
May 2012
A special thanks to all the contributors on the White Island Software and GambasForum, for their
help in improving this guide and of course all developers of Gambas for their effort spent on creating the powerful Basic language, named Gambas.
This guide is dedicated to an old friend, Jos (a.k.a. Yellowmoor), to help him get started with Gambas programming.
I would like to dedicated the 'How To Gambas 3'-series to my three sons Nicky, Luca and Nino.
1
Meanwhile Gambas has been introduced at my job and is being used there as well. The environment has gone from Windows only to a mixed Windows/Linux one.(added September 23th, 2013)
1
2. Foreword
2 Foreword
This guide is the second in the series 'How To Gambas 3'. The guide is aimed at people new
to Gambas and programming and discusses the building of simple standalone GUI applications.
This pre-release 1 is a first public release of a still unfinished guide. Fact that it isn't finished
yet, doesn't mean it can't prove useful to people new to programming in Gambas.
The guide will learn you the basics of making new GUI projects in the Gambas IDE. Drawing
controls on forms, learn to code their events and run the program.
It will explain terminology common to programming and Gambas in specific. You will learn
about user interaction, input and output of data, handling text-based and numeric data, localisation, the basics of loading and saving data to files and of handling images in your application. Besides that Gambas syntax and useful string, arithmetical and other functions are explained and demonstrated.
All is learned in a step by step approach explaining each and every new detail, accompanied
by code, screenshots2 and hands on practice in using the Gambas IDE, typing code, compiling and running code and see things work (or fail).
Often examples are approached in a manner that let's you stumble upon problems that
gradually get solved. This will slowly get you acquainted with detecting problems , different
manners of solving the same problem and a broader insight in the Gambas language in general.
At the end of pre-release 1 you should be capable of building very basic GUI applications,
handling text and numbers, save and load files and images, working with menus and toolbars
and have a basic understanding of concepts like Public, Private, methods, functions, objects,
controls and such.
In the chapters still in development, things like printing data, drawing on a DrawArea, more
complex saving and loading of data, form classes, modules, the Gambas IDE and it's possibilities, folder structures of projects, Gambas components and their function and maybe even
more will be explained.
For now enjoy pre-release 1,
Willy Raets,
September 28th, 2013
Practical note: When you copy/paste code from the code boxes into the Gambas IDE you
might get errors running the code. To prevent this from happening simply copy/paste the code
into a plain text editor first and next copy/paste from the text editor into the Gambas IDE and
you won't have this trouble.
Better practice is to simply type the code directly into the Gambas IDE as this will get you familiar with typing code in the editor and working with the auto-help feature, during typing.
2
All screenshots are made on Linux Mint 13 – Mate 1.4 with English language installed using
Gambas 3.4.2, except otherwise mentioned. Screenshots might look different on your distribution and with your localisation settings.
2
3. Before you get started
3 Before you get started
You will need to have at least Gambas 3.3.x or higher, installed on your system 3. Installing
Gambas will not be covered in this book. 'How to Gambas 3 – Installing Gambas' covers the
installation of Gambas in detail and for different distributions.
You will also need to know some conventions used in this book for clear understanding of the
materials presented herein.
3.1 Background information
When explaining how to built and code in Gambas 3, I will sometimes provide extra background. This extra background is meant to give some deeper insight into the world of both
Linux and Gambas.
This background is not necessary for completing the examples, but will give you a better comprehension of Gambas in general.
This is how background information is presented in this book.
It will give you some more insight on the item being explained.
Background information will be placed in a yellow box.
3.2 Example code
Example code is used to explain Gambas using sample applications that get built up and explained in detail from the scratch.
'Sample code
'
Public Sub Form_Open()
Me.Center
Me.Caption = “Sample application”
End
The Gambas code that you need to write in the examples will be placed in a white box.
3.3 Good Practice
If something is considered as a good practice it will be placed in a green box.
This is how good practice information is presented in this book.
It is advised to start using this good practice in applications you built.
Good practice will make for more effective maintenance of your system or applications.
3.4 Terminal
If you would ever need to run a command in a terminal window it will be placed in a black box.
This means you will need to open a terminal interface like Gnome terminal, LX terminal or
whatever application lets you go to the command line interface on your distribution.
3
Code will most likely work as well in Gambas 3.1.x or higher, although this was not tested.
Just give it a try if that is your situation, since nothing I know of has changed in the
syntax and use of the core Gambas components discussed and used in this guide.
3
3. Before you get started
uname -a
3.5 Warning
If it would ever be needed to get your attention to matters that are of great importance they
will be placed in a red box.
This is an important procedure.
Pay attention as things can go seriously wrong :-)
3.6 Controls and menus
When testing the applications built in Gambas you will need to do things like click on a button
to see if the code does what it is supposed to do.
When, for example, referring to the button with Cancel on it I will refer to it as: Click on the
button Cancel
When for example referring to a menu About... in the menu Help I will refer to it as: Click on
menu Help → About...
4
4. Introduction
4 Introduction
4.1 What is Gambas?
As the Gambas website states: 'Gambas almost means Basic'. With the 'G' for Gambas, the
'a' for almost, the 'm' for means and the 'bas' for Basic. A nice little playing on words.
According to the official website 'Gambas is a free development environment based on a Basic interpreter with object extensions'. It is comparable to a popular counterpart on an mainstream platform.
The person behind the project and main developer is Benoît Minisini from France with the
help of others.
Gambas provides you with an IDE for easy development of GUI applications. Gambas components provide you with extra syntax and functionality to code for things like database access, networking access, CGI web applications, internationalisation and more.
Visit the Gambas Introduction at the official Gambas website for more details.4
IDE or Integrated Development Environment is a software application that provides
comprehensive facilities to computer programmers for software development.1
In Gambas this means you have an environment where you can easily design your forms, put
controls on them (like buttons, text fields, check boxes and so on) and code them in a source
code window.
You get a tree view on the project so you can easily browse from one form design to another
and see other files like icons contained in the project.
The Gambas IDE also has a debugger so you can run applications in development time without
having to make executables or distribution packages, a thing the IDE does as well.
You can add or remove components to the project in the IDE and in this way add or remove
functionality to your applications.
1. Source: http://en.wikipedia.org/wiki/Integrated_development_environment
Gambas provides you with the tools for RAD (Rapid Application Development) through use of
the IDE. This makes GUI application design, debugging and packaging for distribution easy
and by Gambas supporting OOP (see below in yellow), a concept that makes reuse of parts
already built possible, saving time, energy, and reducing errors. No need to do things over
and over again.
Object-oriented programming (OOP) is a programming paradigm using "objects" – data
structures consisting of data fields and methods together with their interactions – to design
applications and computer programs.
Programming techniques may include features such as data abstraction, encapsulation,
messaging, modularity, polymorphism, and inheritance. Many modern programming languages
now support OOP, at least as an option1
1. Source: http://en.wikipedia.org/wiki/Object-oriented_programming
4
http://gambas.sourceforge.net
5
5. Some good practices
5 Some good practices
If you develop applications there are some good practices that can make your life easier. I'll
try to give an overview on how I organise my projects, code and more for Gambas. This is the
way I have done it for my own needs and it is a sort of evolution that took place over the
years of programming in different languages.
This doesn't have to be how you want to organise your projects, code and more, it is just a
suggestion that could prove useful.
5.1 Folder organisation
This is probably not the first thing most of you would think about but to me it is an important
one, especially when having several projects running.
Here is how I organise my folders for Gambas development. I develop in both Gambas 2 and
3. You can do it differently when only developing in Gambas 3.
First I create 2 folders in my home folder or in a folder made for it. One is called 'Development', the other 'Distributions'. This you can simply do from within your File Manager application beloning to your Linux distribution.
5.1.1 Development folder
In my case in the 'Development' folder I create a 'Gambas2' and a 'Gambas3' folder.
Within the 'Gambas3' folder I create following folders:
➢ Application documentation
➢ Gambas3-ArchivedApps
➢ Gambas3-GameZone
➢ Gambas3-Projects
➢ Gambas3-SourceOthers
➢ Gambas3-TestZone
➢ Gambas3-Tools
Illustration 1: Organisation of 'Development' folder
6
5. Some good practices
1. Application documentation
This folder is used to place documentation files made to accompany applications I distribute.
2. Gambas3-ArchivedApps
Archived applications can be any application I haven't looked at for a long time. I never trow
them away, but relocate them to this folder. They can sometimes still be useful just to remember how you done something in those days, or as a base for an entire new application.
3. Gambas3-GameZone
The folder I store my Gambas game projects
4. Gambas3-Projects
The folder I use for all my distributed application projects. Each project will get his own folder
named after the project. This will be done when creating a new project in the Gambas IDE.
5. Gambas3-SourceOthers
In this folder I unpack project source code from other developers they shared. I can then
open them as normal projects in the Gambas IDE. It could be for purpose of checking out
code, testing the application or help solving an error. When not useful they get deleted instead
of archived.
6. Gambas3-TestZone
This folder is for making a quick project for testing something, or for trying out things or for
replicating a question asked on a forum to see if I can come up with a solution. They are no
serious projects, but exactly what the folder says, test zone applications. They often get deleted instead or archived.
7. Gambas3-Tools
The folder I use for applications (libraries) I develop for use in my distributed projects, or for
tools I use myself.
You can make more or less folders to categorise and organise your projects on your system.
You can add new folders later and replace projects. For the projects you will be making in this
guide you could make a 'Gambas3-LearningZone' folder to put them in. All that is up to you.
5.1.2 Distributions folder
This folder contains the distribution packages for all my applications. In my case in the 'Distributions' folder I create a 'Gambas2' and a 'Gambas3' folder.
Within the 'Gambas3' folder I create following folders:
➢ Archived
➢ Website
➢ Zone-Games
➢ Zone-HowToExamples
➢ Zone-Ideas
➢ Zone-Libraries
➢ Zone-MyTools
➢ Zone-PackageInstallers
➢ Zone-Projects
➢ Zone-Testing
1. Archived folder
The 'Archived' folder contains distribution packages of applications no longer maintained.
2. Website folder
7
5. Some good practices
Illustration 2: Organisation of 'Distributions' folder
The 'Website' folder contains information for website of the distributed applications and things
like online version files, data files beloning to certain applications and so on
3. Zone folders
Within the different 'Zone' folders there are folders named after the application they contain
distribution packages for.
Within the application folder there is a folder named after each version release number containing:
➢ A source package of that version of the application
➢ A folder for each distribution an installation package is made for
➢ (If needed) a gambas executable of that version of the application
1. Source package of that version of the application
The source packages will enable you to revert back to a previous version of the application.
2. A folder for each distribution an installation package is made for
The distribution specific folders will be made by the Gambas IDE upon making the packages
if you select so. They will contain both installation and source packages specific to that distribution.
3. A gambas executable of that version of the application
Executables make for easy quick testing by other developers or in a virtual machine. They are
not always required but come in handy in some situations.
8
5. Some good practices
Illustration 3: Application folder with version folders containing the
packages
Note that in Gambas 3 you can make packages for more than just the distributions shown
above.
5.2 Project organisation
Within the Gambas IDE you can also work on organising for your own benefit. It is good practice to make folders in there that contain specific data, like a folder for images or icons.
This can all be done from within the Gambas IDE.
Illustration 4: Organisation of a project folder in the
Gambas IDE
How this all is done will be discussed later in this guide.
5.3 Organising your code
One very important aspect of building applications is to make sure you still understand what
you where doing a year later, when you want to change parts of it or (re)use them somewhere
else.
9
5. Some good practices
The other thing is that, if you built your applications open source, it makes the code more
readable to those looking at it.
5.3.1 Commenting your code
A first good start is by putting comments into your code. Commenting in Gambas is easy. Just
start the line with '
What could you comment about. Well this is what I tend to do:
➢ Identify each class and its function
➢ Describe the functionality of each block of code in one line of comment
➢ Write comments at parts that need improvement (including ideas on improvement)
1. Identify each class and its function
This is an example of the identification comment in a class in one of my projects.
' Gambas class file
'
' --------------------------------------------------' Application: SysInfo
' Class: SysInfo
' Function: Library for system information retrieval
' Author: W.J.L. Raets
' GNU General Public Licence - Version 3
' --------------------------------------------------You could include more in there like maintenance or revisions you do in the code and the date
you did them.
This is especially useful in projects where more that one persons works on the same project.
This way all developers involved will have an idea on what has changed.
But even in your own personal projects you might be happy someday when looking back at ½
year old code for having done this.
2. Describe the functionality of each block of code in one line of comment
This again is an example of describing blocks of code by functionality in one of my projects
(see next page).
The (rest of code) blocks are quite long pieces of code, so I left them out. Without these
simple comments dividing the code into parts that are coded in that specific area I would get
lost in my own code. In the example on the next page I have made the comments bold.
So don't be sparse with commenting your application.
10
5. Some good practices
Static Public Sub ReadDesktopInfo()
Dim sWinMan, sWinManAid, sDeskAid As String
Dim iPosition, iPosB, iPosE, iSwitch As Integer
'======== Find x window manager ==============
Try Exec ["kwin", "--version"] To sWinMan
...(rest of code)
Else
CompWindowManager = Trim(sWinMan)
Endif
' === Determine desktop based on window manager ===
Select sWinManAid
Case "met"
'---- metacity & Gnome 2
… (rest of code)
Case "mut"
'---- mutter & Gnome 3
… (rest of code)
End
3. Write comments at parts that need improvement
Again, this will only help you. I have had to deal with code that worked on certain distributions
and gave errors on others.
Being clear with comments on what distros gave trouble and needed further investigation enabled me to gradually get it working on all distros.
Again an example of how that could look with the comments made bold.
Static Public Sub ReadDbInfo()
Dim sMySql, sSqlite, sPostGreSql As String
Dim iPosB, iPosE As Integer
'Stable on most returned distros - LXDE a bit troublesome
'TODO: sqlite3 needs testing results returned for analysing
'TODO: figure out sqlite retrieval on an LXDE based desktop
Try Exec ["mysql", "-V"] To sMySql
'==check for Mysql ==
… (rest of code)
End
And believe me, one day when you look back at an application you built and forgot about you
will be very happy with all your comments in your code.
Some special keywords like 'TODO: in your comments will generate an inline task. This
makes it easy tracking code, where things need to be done and also works very well as a reminder of things that still need to be done in your code.
Later in this guide I will go into this a bit further in an example application.
5.3.2 Clear choices for names
Picking the right names for variables you use in your code can make for more readable code.
Two things I tend to do are:
➢ Pick a name that describes the content
➢ Begin the name with a lower case letter identifying the type of content it represents
1. Pick a name that describes the content
11
5. Some good practices
Names of variables that suggest what their content will be, are easier to comprehend and remember when reading or writing many lines of code.
In one of my applications I try to extract the window manger used on the system. An easy
name for that could be WinMan.
The name tells us that the information on window manger retrieved on the system will be
stored in the variable named WinMan.
2. Begin the name with a lower case letter identifying the type of content it represents
Going back to the previous example of the window manager being stored in a variable named
WinMan it is best make some minor adjustment to the name to identify the type of content.
The content that will be extracted from the system will contain text, so in Gambas it's type is
String. Now to indicate that the variable WinMan will contain data of the type String I named it
sWinMan.
By putting a lower case 's' in front of 'WinMan' I identify the variable as being a string containing window manager information.
In the course of this guide and all the examples you will get more examples on how you could
use this to your benefit.
5.3.3 Indenting code
Another good practice for clear and readable code is indenting code.
For example say you want to check if some condition is met and do one thing or another depending on the result of the condition.
In Gambas you would code this with an If ...Then .. .Else. Lets say you want to test if our
sWinMan is empty or not. I will first give an example of less readable code without any indenting.
Static Public Sub Test()
Dim sWinMan As String
sWinMan = TextBox1.Text
If Len(sWinMan) = 0 Then
sWinMan = “Unable to trace”
Else
sWinMan = Trim(sWinMan)
Endif
End
Next the same code but with indenting applied for more readable and structured code.
Static Public Sub Test()
Dim sWinMan As String
sWinMan = TextBox1.Text
If Len(sWinMan) = 0 Then
sWinMan = “Unable to trace”
Else
sWinMan = Trim(sWinMan)
Endif
End
The indenting makes clear what part is executed if the condition is met and what part is executed if the condition isn't met.
12
5. Some good practices
In the examples provided in this guide you will get to see more examples of indenting as I use
it in all my coding.
5.3.4 Eliminate repeating code
1. Subroutines and functions
When you find that you have code in a form class that repeats itself it would make for better
and more readable code to abstract it into a subroutine or function that can be called.
This also makes for easier maintenance for the code as you only need to change it at one
place in your form class, instead of several.
You will see examples of this in this guide.
2. Modules
When you find that you have code in several form classes repeating itself or performing likewise tasks, try to abstract it and place it in a module. This way it can be used within the entire
project.
This also makes for easier maintenance of the code as you only need to change it at one
place in the project instead on several forms classes.
Modules are actually exported classes, that is why they work for the entire project.
You will get to see some examples on using modules in this guide.
3. Classes
Classes can be considered as the templates for objects.
When having likewise code in modules in different applications you should consider making a
new project and copying the module code into classes, abstract some code and finally Export
these classes and make a library out of this application for installation on your or other
people's system.
Use this library in all the projects you have a need for its provided functionality.
This also makes for easier maintenance of the code as you only need to change it in one project (the library) instead of in each project over and over again.
The scope of this book does not cover libraries and classes, other than the Form classes.
13
6. A first GUI application: TextPlay
6 A first GUI application: TextPlay
Lets get started with using Gambas 3 and build a first simple GUI application.
6.1 What will be done in this chapter
Main focus will be creating a form with some controls, write some simple code for the controls
and run the application.
This will involve
➢ Opening Gambas IDE and make a new project
➢ Make a main form
➢ Place four controls on the form (Two buttons, a TextBox and a Label)
➢ Write some simple code
➢ Run the application from Gambas IDE
You can learn about:
➢ How to make a new project in Gambas3
➢ Working with the Gambas IDE
➢ Button, TextBox and Label controls
➢ Event driven programming, objects, methods and properties
➢ User interaction (input from user, output from application)
6.2 Starting a new project
First you start Gambas from terminal or menu depending on how you installed it5.
On first opening Gambas it should show the examples.
Illustration 5: Gambas 3.4.1 opening screen
5
See 'How To Gambas 3 – Installing Gambas'
14
6. A first GUI application: TextPlay
Now click on New Project... to make a new project. In the 'New project' screen you select the
type of application you wish to build.
Illustration 6: 'New project' screen step 1. Select the
type of application
Select Graphical application as that is what you are going to build, a GUI application.
No further options need to be selected.
Illustration 7: 'New project' screen step 2. Select the
folder for the new project
15
6. A first GUI application: TextPlay
Browse to the folder /Development/Gambas36 and select it.
Now right click and select Create directory in the menu.
Illustration 8: Create a new folder for Learning projects
Name the folder Gambas3-Learning and select it.
Illustration 9: Select the folder 'Gambas3-Learning'
Next click button Next.
6
See 5.1. Folder organisation
16
6. A first GUI application: TextPlay
In the 'New project' screen step 3 you can name both the folder where the project will be located and the name the actual application will have. They can be different if you like.
Illustration 10: 'New project' screen step 3. Name the
project folder and project
For both 'Project name'7 and 'Project title'8 type TextPlay.
Next click the button OK and you get a message a new project has been created.
Illustration 11: Message when project has been created
successfully
7
8
Name of the folder the project will be located in and the name of installed executable.
Name of the actual application as used in a distro menu once installed.
17
6. A first GUI application: TextPlay
After clicking OK the Gambas 3 IDE opens with a new empty project named TextPlay.
Illustration 12: New project 'TextPlay' opened in Gambas 3 IDE
You have just created a new project in Gambas for building a first GUI application.
Each project opened in IDE has 4 major zones:
➢ Zone 1: Menu and toolbar zone
➢ Zone 2: Project browser
➢ Zone 3: Working area
➢ Zone 4: Debug area
They will gradually make more sense when working with the examples that will be built in this
guide.
6.3 Creating a form and controls
Next step is to create a form with some controls on it. Since you chose to create a new
'Graphical application' a form is already in place named FMain9.
You will find this form in the Project browser (zone 2) in the folder 'Sources'.
Illustration 13: FMain in Sources folder of the project
9
Note the small black arrow in the project browser in front of the FMain icon. That arrow indicates that this form is the first one to run, after starting the application
18
6. A first GUI application: TextPlay
Just double click Fmain and the empty form will be in the Working area (zone 3)
Illustration 14: Empty form in IDE
In the 'Working area' (zone 3) you see an empty form and at the right of it a box with 'Properties/Hierarchy'.
Underneath the 'Properties/Hierarchy' you will find a ToolBox to build the controls.
The ' Properties/Hierarchy' is only visible when forms are in the 'Working Area'. If code is
viewed in the 'Working Area' there will be no ' Properties/Hierarchy' box nor Toolbox.
6.3.1 Placing controls on a form
First you will place a Label on the form.
For that you go to the ToolBox and hover your mouse over each of the icons until you find the
'Label' icon (a big A).
19
6. A first GUI application: TextPlay
Illustration 15: Label icon in
ToolBox
Click on the Label icon and next drag a rectangle on the form.
Illustration 16: Label control drawn on the form
This should give you a Label control.
Next search the ToolBox for a TextBox icon.
Illustration 17: TextBox icon
in ToolBox
20
6. A first GUI application: TextPlay
Click on the TextBox icon and next drag a rectangle on the form.
Illustration 18: TextBox control drawn on the form
This should give you a TextBox control.
Next search the Button icon in the ToolBox.
Illustration 19: Button icon in
ToolBox
Click on the Button icon and drag two rectangles on the form.
Illustration 20: Two button controls drawn on the form
This should give you two buttons.
21
6. A first GUI application: TextPlay
6.3.2 A closer look at the controls
First select the Label by clicking on it. The 'Properties/Hierarchy' Box will show properties of
the selected control, Label1.
You are about to change some of them and see what they do.
Note that when you selected Label1 in the 'Properties/Hierarchy' Box it says 'Label1 Label'
(Label1 is the name of the control and Label is the type of control).
In the box below you can find Help on Label (gb.gui).
First click on the 'Alignment' property on Normal and a selection box will appear. Select
Right.
Illustration 21: Select Alignment of
the Label control
22
6. A first GUI application: TextPlay
This will align the text of the label to the right.
Illustration 22: Label1 aligned right
Next go to the 'Text' property and click on Label1 and type Enter your name:
Illustration 23: Label1 Text property changed
You will see the typed text appear in your label on your form. Your label is now ready for use
in the application.
Label controls are usually used in combination with an input control. The Label is used to make
clear what the input control is for and should contain.
For example a Label could show 'Name', followed by an input control like a TextBox where the
user can type his/her name.
This doesn't mean you can use Labels otherwise.
Next lets focus on the other controls by means of exercise. Here is what needs to be done:
➢ Select TextBox1 and empty the Text property.
➢ Select Button1 and change the Text property to 'Show'.
➢ Select Button2 and change the Text property to 'Clear'.
Illustration 24: Controls after changing the properties
Your end result should look like the illustration above.
23
6. A first GUI application: TextPlay
6.4 Coding, testing, coding, testing...
Now that you have finished the making and customising of the form and controls focus will go
to make it do something.
6.4.1 Objects, properties, events and methods
You will first need to understand some basics before continuing.
The form and all the controls you made are all objects.
There are different kinds of objects. Like the form is an object, each control is an object,
classes are objects. Some objects are creatable10, others are not.
As you have seen objects have properties, but objects can also have events and methods.
Properties are about the object. For example a Button control can have a property Text that
contains the text shown on the Button.
Events can happen to an object. For example a Button control can have the event click.
This means that when this event happens to the object you can make something happen (in
other word you need to code what needs to happen).
Methods can be done by an object. For example a Button control has the method Show.
You can use this method to show the Button or hide it.
This is a very basic explanation, but enough to comprehend what you will be doing next.
6.4.2 Write some code and test (round 1)
Now lets start with the fun part, the actual coding or writing Gambas code.
This is what you want to happen when running your code:
1. You want to type your name in the TextBox.
2. When clicking on Button 'Show' you want a message box with the name typed in the
TextBox.
3. When clicking on the Button 'Clear' you want to empty the contents of the TextBox.
Let's analyse this and divide it into two pieces:
1. User input:
- Type name
- Click on Button Show
- Click on Button Clear
2. Application output:
- Message with name
- Clear a TextBox
In the user input you can see some events (or things that can happen to an object). Text being entered by the user in a TextBox and clicking on buttons. So these are events where you
need to write your code.
In the application output you see what needs to happen, so what you need to code.
Now for the text being entered nothing realy needs to be coded as things happen when clicking the buttons. Clicking the Show button needs to show you a message box with the entered
text. Clicking the Clear button needs to clear the entered text.
10
A "creatable" object is an object that can be instantiated by itself.
24
6. A first GUI application: TextPlay
Right click on button Show, select Event → Click.
Illustration 25: Select Event Click for button control
This will open the FMain.Class in a new tab in the 'Working Area'.
Illustration 26: FMain.class
25
6. A first GUI application: TextPlay
As you see the cursor is positioned in Public Sub Button1_Click().
In short this means that this Subroutine (Sub) belonging to object Button1 and taking place on
the Event Click is Public for Fmain.class.
Write this code for Public Sub Button1_Click():
Public Sub Button1_Click()
Message(TextBox1.Text)
End
The object named TextBox1 holds the text entered by the user in the property Text. To get
there you write TextBox1.Text11.
The method Message() displays a String value in a message box.
Next double click FMain in the project browser (or click tab FMain.form) to go back to the
form. Right click button Clear and select Event → Click.
Write this code for Public Sub Button2_Click():
Public Sub Button2_Click()
TextBox1.Text = “”
End
The = “” (2 times double quote) sets an empty string value (or Null value) to the
TextBox1.Text property. Strings are anything in between double quotes. Note that copying the
code with quotes into IDE will generate errors. You need to type the quotes in IDE.
Next step is to test this little application.
For this you go to menu Debug → Run (or hit F5 on your keyboard).
Illustration 27: Menu Debug -> Run to test the application
11
You will notice when tying code in Gambas IDE you will get some help along the way. Like
when typing the name of a control followed with a dot you will see all methods, functions,
constants and properties of that control.
26
6. A first GUI application: TextPlay
Now lets see if the application does what you want it to do.
Enter your name in the TextBox and click Show. A message with the entered name will appear. Click OK to close the message.
Illustration 28: Application running with message shown
Next click Clear and the TextBox will be empty.
So all seems to work as expected, but that doesn't mean you are ready yet as there certainly
is some room for improvement.
6.4.3 Code some improvements and test (round 2)
As you have seen the message box centres on the screen, the application is on the top-left of
the screen. It would look nicer if the application was centred on the screen as well.
Another thing that would be nice is that, in case no text is entered and the show button would
be clicked the message would ask you to enter some text first.
So these added requirements will mean you need to code some event belonging to Fmain to
make it appear centred on the screen.
To figure out what event to code for Fmain simply select Fmain (in case a control is selected
simply click on an empty space on the form to select it), right click and select menu Event →
Open. You will need the event Open because you want the form to centre when it opens12.
Write this code for Public Sub Form_Open():
Public Sub Form_Open()
Me.Center
End
Me refers to Fmain. Center is the method that will center FMain.
12
Another option is to simply double click the form to go to Form_Open()
27
6. A first GUI application: TextPlay
You will also need to add a test to the Click event for button Show to act one way or the other
depending on the result of the test. What needs testing is if text has been entered into TextBox1.
So you need to check the property Text if it is empty or not.
Change the code for Public Sub Button1_Click() to:
Public Sub Button1_Click()
If IsNull(TextBox1.Text) Then
'Test if name entered
Message(“First fill in a name”)
Else
Message(“The name entered is “ & TextBox1.Text)
Endif
End
IsNull(TextBox1.Text) will test if TextBox1.Text is empty13 and return True if it is. If true a message will tell you to first fill in a name. If false the name will be shown, but a bit more nicer this
time. Note: If IsNull(TextBox1) Then is the same as: If IsNull(TextBox1.Text) = True Then.
IsNull() is a datatype function of type Boolean, meaning it will be true or false. Depending on
the expression tested.
IsNull(expression)
Returns True if expression is NULL.
NULL means:
- The NULL constant
- A null object reference
- A zero length string
- A null date
- An uninitialized variant
More on IsNull() see http://gambasdoc.org/help/lang/isnull?ja&v3
If expression Then..Else..Endif
Behind If you need a test (expression) that returns a Boolean (True/False)
The code for Then is run when test returns true.
The code for Else is run when test returns false.
Endif ends the code block.
You can use logic operators (like And and Or) in the expression to test for more than one
condition.
More on If see http://gambasdoc.org/help/lang/if?v3
Message() needs to contain string values. Text between quotes is considered string as is the
content of a Text property. To connect them together to one string you use &.
Next it is time to test. Press F5 and next click the button Show.
13
A TextBox with a space entered by the user might look empty but actually isn't as it is not
equal to Null (it contains a space and thus as string looks like “ “ and has a length of 1
instead of looking like this “” with a length of 0).
28
6. A first GUI application: TextPlay
Illustration 29: Message when no name entered
As you can see the application is now centred on the screen. Clicking Show results in a message to first fill in a name.
Now click OK enter a name and click Show again.
Illustration 30: Message when name entered
You see this results in a nicer result than in the first round of testing. Congratulations, you
have just build a first GUI application in Gambas 3.
Now close the project in menu File → Quit. This will also close Gambas and set you at the
point to start for the next chapter.
29
7. Extending application TextPlay
7 Extending application TextPlay
7.1 What will be done in this chapter
Main focus will be on adding some more controls and code to further explore Gambas and
run the application.
This will involve:
➢ Open an existing project for changes
➢ Add new controls (Radio Button, CheckBox, TextArea, Frame)
➢ Add/change code to events of some of the controls
➢ Run the application from IDE
You can learn about:
➢ Working with the Gambas IDE
➢ More controls
➢ More properties, events and methods
➢ User interaction
7.2 Open an existing project
First you start Gambas and it should open on the Recent Projects tab. If not click on it.
Illustration 31: Gambas welcome screen 'Recent projects'
The project TextPlay should be in the list somewhere on top if recently opened14. Click on
TextPlay to open in IDE.
14
Or it could be the only application in there if TextPlay is your first Gambas 3 application.
30
7. Extending application TextPlay
7.3 Modify main form and add controls
Next step will bring us back to Fmain to redesign the form for some additional controls to be
added later.
To get get there just double click Fmain in the project browser.
Once you have the FMain in the 'Working Area' move your mouse to middle of the right border of the form.
Illustration 32: Mouse appearance will change where the pointer
is
Your pointer will change appearance and you will be able to drag the form wider. So drag the
form a bit wider.
Illustration 33: Form dragged wider and Label and TextArea
selected
Next click the Label, hold down ctrl key and click the TextBox.
31
7. Extending application TextPlay
This will select both of them and you will be able to drag them a bit to the left, as there is still
some room left over.
Illustration 34: Drag the buttons to the bottom of the form
Next select button Show, hold ctrl key and select button Clear. Drag them to the bottom of
the form.
Illustration 35: Result after adapting the form
Your form should look like in the illustration above.
32
7. Extending application TextPlay
7.3.1 Copy controls on the form
In the next step you are going to add a Label, TextBox and a Button to the form. Instead of
using the ToolBox and draw them you will simply copy and paste existing controls on the form.
For this first select the Label and TextBox and next press ctrl+c (to copy the controls). Next
press ctrl+v (to paste the controls on the form).
Illustration 36: Pasted controls on the form
Now drag the newly pasted controls below the ones already there.
Illustration 37: Controls dragged to the spot you need them
Next select one of the buttons, copy/paste it and drag it to the bottom-left of the form.
Illustration 38: Result after copy/pasting all needed controls
33
7. Extending application TextPlay
7.3.2 A closer look at the controls
Now that all the new controls are in place lets have a closer look at some of their properties.
First select the most top Label and check its Name property, Alignment property and Text
property in the 'Properties/Hierarchy' Box. Now select the other Label and do the same
check.
You will find one Label named Label1, the other named Label2. All other properties (except
for X and Y location on the form) are copied from Label1 to Label2 during the Copy/Paste of
Label1.
When copy/pasting controls their name will always be a copy of the name of the original control
with an added number. The number will be one higher than the previous one.
Example:
If you copy/paste Label1, the copy will be named Label2. If you next copy/paste either Label1
or Label2 the next copy will be named Label3
Select the Text property for Label1 and type Enter your first name:
Illustration 39: Label1 after changing the Text property
Next select TextBox1. Change the Name property to tbxFirstName. Next select TextBox2
and change the name property to tbxName.
Illustration 40: Name properties of both TextBoxes changed
Some more adaptations as a little exercise:
- Change the Name properties of the left button to btnShow
- Change the Name properties of the middle button to btnClear
- Change the Name properties of the right button to btnAdd
- Change the Text properties of the right button to Add
34
7. Extending application TextPlay
Illustration 41: Main form after the changes in the exercise
In case I do not use the name of a control on a form in code I will keep the original name given
to the control when first drawn on the form (or copied onto the form).
In case I am going to use the name of the control in code, I like to have a name that makes
some sense. Two things are important to me:
1. I would like to know the type of control
2. I would like to get an idea what the control is for
For this I have developed my own system, based on the naming of variables according to type
(see 5.3.2 Clear choices for names). I use three lower case letter to identify the type of control,
next a Capital letter followed by lower case identifying the purpose of the control.
Some examples:
TextBox1 → tbxFirstName
Button1 → btnShow
Label3 → lblResult
TextArea1 → txaResult
CheckBox1 → cbxShow1
RadioButton1 → rbnYes
You will get to see more of this as the guide continues.
If all changes are met have a look at the FMain.class. Click the tab Fmain or in the project
browser right click FMain and select Edit code
35
7. Extending application TextPlay
Illustration 42: Names of buttons changed in Fmain.class as well
You will notice that changing the name properties for Button1 and Button2 also changed their
names in the FMain.class.
Be aware that, when changing a Name property of a control on a form, only the form class the
control belongs to, will change the name in code as well.
Now two more things are left to do and they make for a great exercise as well:
- Add a Label (below tbxName) to the form, name it lblResult
- Add a TextBox (below lblResult) to the form, name it tbxResult and set ReadOnly to True
- Add a TextArea (below tbxResult) to the form, name it txaResult and set ReadOnly to True
- Empty the Text property of lblResult and txaResult
Illustration 43: Main form after adding two more controls
The result should look like the illustration above.
36
7. Extending application TextPlay
7.4 Coding, testing and adapting
In this part you are first going to add new code, test it, improve it, test it again as so on.
You will not always start with the best solution but gradually work towards one and this is
done on purpose (you will be seeing more of that). This way you will learn what can and can't
be done in Gambas. You will learn what can go wrong and how to fix it. It is like learning to
ride a bicycle, it is falling down that makes for a greatest learning curve.
7.4.1 Coding and testing (round 1)
First focus will be to make the Add button do something. Since there are two input fields now
(tbxFirstName and tbxName) it would be nice to let the Add button 'add' both names together
and show them in lblResult, tbxResult and tarResult. Let's code for this.
Select button Add, right click and go to Event → Click
Type following code for Public Sub btnAdd_Click()
Public Sub bntAdd_Click()
Dim sResult As String
sResult = tbxFirstName.Text & “ “ & tbxName.Text
lblResult.Text = sResult
tbxResult.Text = sResult
txaResult.Text = sResult
End
Dim (short for Dimension) is to declare local variables and their types. In Gambas you always
need to declare your variables before you can use them in your code.
The & is used to add different strings together to one string. In this case the string in tbxFirstName.Text followed by a space (“ “) and the string in tbxName.Text. The space is to separate
the first name from the name.
Now run the project type in your first name and name and click Add to see what happens.
Illustration 44: Result after clicking button Add
Now click Clear and see what happens. As it seems only the first name gets cleared. It would
be nice if not only first name gets cleared but name and the results as well.
37
7. Extending application TextPlay
Next click in the first name box and press Tab key a few times. The order of how Tab jumps
from one control to the other can be determined by you.
So here is two points for change.
Note the difference in how the result is shown in lblResult, txbResult and txaResult.
Also note that the lblResult, tbxResult and txaResult are not editable, meaning you can't
change the content. For tbxResult and txaResult you needed to set property ReadOnly to
True. Labels don't have a ReadOnly property as they are default read only.
7.4.2 Adapting, coding and testing (round 2)
First have a look at the order controls will be selected when using the Tab key. For this go to
the 'Properties/Hierarchy' Box of Fmain and click on the Tab Hierarchy.
Illustration 45: Hierarchy of the controls on main form
You can select a control in the Hierarchy Box and move it up or down, changing the order it
will be selected.
The only fields that need to be 'Tabbed' are FirstName, Name and the three buttons. So move
them up in the hierarchy. Label1 and Label2 are of no importance so move them down.
Illustration 46: Hierarchy after adaptation
38
7. Extending application TextPlay
Next click on the Properties Tab and select Label1, Label2, lblResult, tbxResult and txaResult.
In the properties scroll to the property NoTabFocus and set this to True
Illustration 47: Set selected controls NoTabFocus property to True
This should take care of the Tab key order.
Now lets have a look at the code of btnClear and adapt it to meet your requirements.
Change code for Public Sub btnClear_Click() to:
Public Sub btnClear_Click()
'tbxFirstName.Text = “”
tbxFirstName.Text = Null
tbxName.Text = Null
lblResult.Text = Null
tbxResult.Text = Null
txaResult.Clear
End
The ' before tbxFirstName.Text = “” makes the line a comment. So it will not be executed.
Here you just try another manner of clearing the content using Null.
When replacing a piece of code with new code a good practice is to comment the old code
rather than deleting it. Next write the new code below the commented code.
If the new code turns out to be problematic or buggy, you can delete the new code and remove
the comments from the old one, rather than having to code it all over again.
If the new code turns out a success you could consider removing the old (commented) code.
The txaResult could be cleared using txaResult.Text = Null but I wanted to show you another
way of clearing content. Just play around with the different options and see what works and
what doesn't if you want to learn some more.
One more feature would be nice to add. When clicking Add if one of the name boxes is empty
you should be told that it is empty and set the focus on that box.
For this you will need to adapt the code for the btnAdd.
Change the code for Public Sub btnAdd_Click() to:
39
7. Extending application TextPlay
Public Sub bntAdd_Click()
Dim sResult As String
If IsNull(tbxFirstName.Text) Then
Message(“Fill in first name”)
tbxFirstName.SetFocus
Else
If IsNull(tbxName.Text) Then
Message(“Fill in name”)
tbxName.SetFocus
Else
sResult = tbxFirstName.Text & “ “ & tbxName.Text
lblResult.Text = sResult
tbxResult.Text = sResult
txaResult.Text = sResult
Endif
Endif
End
First you test if tbxFirstName is empty. If so a message will be displayed and focus will be set
to First Name box (tbxFirstName.SetFocus → SetFocus is a method that gives focus to the
control).
If tbxFirstname is not empty you test if tbxName is empty. If so a message is displayed and
focus is set to the Name box.
If tbxName is not empty the result will be shown.
As you can see you can use an If..Then..Else in another If..Then..Else.. Indenting will make
clear where each block of the If..Then..Else.. is resided.
Now it is time to run the application.
First click on Add without entering names. See what happens.
Next enter a name for First Name and click Add and see what happens.
Illustration 48: Clicking Add without filling in a name
40
7. Extending application TextPlay
Next enter a name for Name and click Add and see what happens.
Next click the Clear button and see what happens.
If all is well the code should be working as supposed to.
7.4.3 Adding new controls, code and test (round 3)
For the next part you need to go back to the form design.
Place three CheckBoxes and three RadioButtons on the form.
Illustration 49: Three CheckBoxes and three RadioButtons
Next run the application and click on the three CheckBoxes, then click on the three RadioButtons and note the difference.
Illustration 50: All CheckBoxes selected, only one
RadioButton
Where all three CheckBoxes can be selected only one RadioButton can at any given time.
Keep that in mind.
Now back to form design.
41
7. Extending application TextPlay
Here is what you need to do (yes, exercise time):
- Change RadioButton1 name properties to rbtLine1, Text properties to 1 Line
- Change RadioButton2 name properties to rbtLine2, Text properties to 2 Lines
- Delete RadioButton3
- Change CheckBox1 name properties to cbxFirstName, Text properties to Add
- Change CheckBox2 name properties to cbxName, Text properties to Add
- Change CheckBox3 Visible property to False
What you require is when 1 Line is selected clicking the button Add shows the information in 1
Line. When 2 Lines is selected clicking the button Add shows the information in two lines.
But that is not all. First name will only be added if cbxFirstName is selected, Name will only
be added if cbxName is selected.
Next you need to code Add button to incooperate the new requirements.
When a CheckBox is selected its value is set to -1, if it is deselected its value is set to 0.
When a RadioButton is selected its value is set to True, if not selected it is set to False.
So this is what you need to to be able to test what needs to be done.
Lets take it step by step. First you code for the RadioButtons to work.
Change the code for Public Sub btnAdd_Click() to:
Public Sub bntAdd_Click()
Dim sResult As String
If IsNull(tbxFirstName.Text) Then
Message(“Fill in first name”)
tbxFirstName.SetFocus
Else
If IsNull(tbxName.Text) Then
Message(“Fill in name”)
tbxName.SetFocus
Else
If rbtLine1.Value Then
sResult = tbxFirstName.Text & “ “ & tbxName.Text
Else
sResult = tbxFirstName.Text & “\n“ & tbxName.Text
Endif
lblResult.Text = sResult
tbxResult.Text = sResult
txaResult.Text = sResult
Endif
Endif
'1 line selected
'2 lines selected
'\n generates a new line
End
As you can see only rbtLine1 gets tested. As there are only two RadioButtons one of them will
always be selected. So if rbtLine1 is not selected rbtLine2 is.
Run and see if this first part of code does the job. Just see what happens and pay special attention to the different result outputs when 2 Lines is selected.
42
7. Extending application TextPlay
Illustration 51: Result of 2 lines selected
As you can see in the illustration above a TextBox can not hold two lines off text. Both Label
and TextArea can. The strange character in the TextBox is the line feed shown (“\n”).
Next lets add the code for the CheckBoxes and remove the TextBox as it is of no use any
longer.
Back to Form design:
- Remove tbxResult
- Check Fmain.class code if tbxResult is used and remove if needed.
Again a nice exercise. And if you might forget to remove tbxResult from code some where,
don't worry, IDE will tell you once you try running the application. Just so you know.
Next change the code for Public Sub btnAdd_Click() to:
Public Sub bntAdd_Click()
Dim sResult As String
Dim iSwitch As Integer
'iSwitch will be used to determine what needs to be shown
iSwitch = 0
'
'Test if first name needs to be added before checking if field is empty
If cbxFirstName.Value = -1 Then
If IsNull(tbxFirstName.Text) Then
Message(“Fill in first name”)
tbxFirstName.SetFocus
iSwitch = -1
Else
iSwitch = 1
Endif
Endif
43
7. Extending application TextPlay
'Test if Name needs to be added before checking if field is empty
If iSwitch <> - 1 Then
If cbxName.Value = -1 Then
If IsNull(tbxName.Text) Then
Message(“Fill in name”)
tbxName.SetFocus
iSwitch = -1
Else
If iSwitch = 1 Then
iSwitch = 12
Else
iSwitch = 2
Endif
Endif
Endif
Endif
'
'Check iSwitch what needs to be done
If iSwitch <> -1 Then
Select iSwitch
Case 1
'Show first name
sResult = tbxFirstName.Text
Case 2
'Show name
sResult = tbxName.Text
Case 12
'Show first name and name
If rbtLine1.Value Then
'Check for 1 line
sResult = tbxFirstName.Text & “ “ & tbxName.Text
Else
sResult = tbxFirstName.Text & “\n“ & tbxName.Text
'\n generates a new line
Endif
End Select
lblResult.Text = sResult
txaResult.Text = sResult
Endif
End
iSwitch is set to -1 every time one of the name boxes needs to be filled in and gets the focus.
In such a case nothing further needs to be tested or shown.
Select expression Case expression End Select
Select enables you to test for different results of one and the same expression.
Behind Case you need an expression
Each Case can be tested against the expression behind Select (as long as types match).
You can use Case Else for all other outcome if needed
End Select ends the code block.
Expression in example code above is iSwitch of type Integer. So behind the Case you need an
Integer value or expression to test possible outcome of iSwitch.
More on select see http://gambasdoc.org/help/lang/select?v3
44
7. Extending application TextPlay
In an expression you can use operators to make comparisons.
a < b → a smaller than b
a = b → a equals b
a <= b → a smaller than or equal to b
a > b → a bigger than b
a >= → a equal to or bigger than b
a <> b → a different from b
You can compare both number values and strings. For strings alphabetic order is used to
determine outcome.
10 = 11 → returns false
10 < 11 → returns true
“Word” = “None” → returns false
“Word” = “Word” → returns true
“Word” < “None” → returns false
“Word” >= “None” → returns true
More on operators evaluation order see http://gambasdoc.org/help/lang/evalorder?v3
More on string operators see http://gambasdoc.org/help/cat/stringop?v3
More on arithmetic operators see http://gambasdoc.org/help/cat/arithop?v3
Now back to running the project. If you get errors you probably forgot to remove tbxResult
somewhere in the code. Fix it.
Type a first name and a name and select only first name to add. Next click Add and see what
happens.
Now select name to add and deselect first name. Click Add and see what happens.
Now select both and click Add to see what happens.
Illustration 52: Clicked button Add with only Name selected
It should all work as expected.
45
7. Extending application TextPlay
7.4.4 Add some last controls, code and test (round 4)
Lets complicate things a bit more by adding some more requirements.
First you would like to enter Country as well, and have a CheckBox to Add. Further more you
would like the option to present the information in 3 lines as well.
And last, but not least, you want to be able to determine what to Show when clicking button
Show. Outcome could be either first name, name or country.
So lets start with yet another exercise:
- Place a new Label and TextBox below Label2 and tbxName to hold the country information
- Name the new TextBox tbxCountry
- Adapt the properties of both controls to confirm to those of Label2 and tbxName
- Add a new RadioButton and name it rbtLine3
- Change rbtLine3 properties to confirm to the other two RadioButtons
- Make CheckBox3 visible again and name it cbxCountry
- Adapt properties to confirm to the other CheckBoxes
As you might notice the instructions get less detailed, so more will be up to you. This is done
intentionally. Just follow the logic of name and text properties already on the form and see if
you manage.
Don't forget to check the hierarchy of the controls on the form!
Illustration 53: New controls added and adapted
First let's focus on code to make tarResult show proper text when clicking btnAdd.
For this you will need to add some code to the btnAdd_Click routine.
Public Sub bntAdd_Click()
Dim sResult As String
Dim iSwitch As Integer
'iSwitch will be used to determine what needs to be shown
iSwitch = 0
46
7. Extending application TextPlay
'
'Test if first name needs to be added before checking if field is empty
If cbxFirstName.Value = -1 Then
If IsNull(tbxFirstName.Text) Then
Message(“Fill in first name”)
tbxFirstName.SetFocus
iSwitch = -1
Else
iSwitch = 1
Endif
Endif
'
'Test if Name needs to be added before checking if field is empty
If iSwitch <> - 1 Then
If cbxName.Value = -1 Then
If IsNull(tbxName.Text) Then
Message(“Fill in name”)
tbxName.SetFocus
iSwitch = -1
Else
If iSwitch = 1 Then
iSwitch = 12
Else
iSwitch = 2
Endif
Endif
Endif
Endif
'--------- ADDED CODE -----'Test if Country needs to be added before checking if field is empty
If iSwitch <> - 1 Then
If cbxCountry.Value = -1 Then
If IsNull(tbxCountry.Text) Then
Message(“Fill in a country”)
tbxCountry.SetFocus
iSwitch = -1
Else
If iSwitch = 1 Then
iSwitch = 13
Else
If iSwitch = 2 Then
iSwitch = 23
Else
If iSwitch = 12 Then
iSwitch = 123
Else
iSwitch = 3
Endif
Endif
Endif
Endif
Endif
Endif
'---------- END ADDED CODE ------
47
7. Extending application TextPlay
'
'Check iSwitch what needs to be done
If iSwitch <> -1 Then
Select iSwitch
Case 1
'Show first name
sResult = tbxFirstName.Text
Case 2
'Show name
sResult = tbxName.Text
Case 12
'Show first name and name
rbtLine1.Value Then
'Check for 1 line
sResult = tbxFirstName.Text & “ “ & tbxName.Text
Else
sResult = tbxFirstName.Text & “\n“ & tbxName.Text
'\n generates a new line
Endif
'----------- ADDED CODE -----------------Case 3
'Show country
sResult = tbxCountry.Text
Case 13
'Show first name and country
If rbtLine1.Value Then
'Check for 1 line
sResult = tbxFirstName.Text & “ “ & tbxCountry.Text
Else
sResult = tbxFirstName.Text & “\n“ & tbxCountry.Text
Endif
Case 23
'Show name and country
If rbtLine1.Value Then
'Check for 1 line
sResult = tbxName.Text & “ “ & tbxCountry.Text
Else
sResult = tbxName.Text & “\n“ & tbxCountry.Text
Endif
Case 123
'Show first name, name and country
If rbtLine1.Value Then
'Check for 1 line
sResult = tbxFirstName.Text & “ “ & tbxName.Text & “ “ & tbxCountry.Text
Else
If rbtLine2.Value Then
'Check for 2 lines
sResult = tbxFirstName.Text & “ “ & tbxName.Text & “\n “ & tbxCountry.Text
Else
sResult = txbFirstName.Text & “\n“ & txbName.Text & “\n “ & txbCountry.Text
Endif
Endif
'----------- END ADDED CODE -----------------End Select
lblResult.Text = sResult
txaResult.Text = sResult
Endif
End
Next add one line of code to the btnClear_Click routine
48
7. Extending application TextPlay
Public Sub btnClear_Click()
'tbxFirstName.Text = “”
tbxFirstName.Text = Null
tbxName.Text = Null
'– ADDED CODE -tbxCountry.Text = Null
'-- To clear the checkboxes
cbxFirstName.Value = 0
cbxName.Value = 0
cbxCountry.Value = 0
'– END ADDED CODE -lblResult.Text = Null
tbxResult.Text = Null
txaResult.Clear
End
Time to test the application. Hit F5 to run the application. Fill in some values and check if
everything works as expected.
Illustration 54: Testing the new code
Also try using the button Clear to see if everything clears up well.
Everything should work just fine, if not check your code to see if you haven't made a mistake
somewhere.
Now let's focus on the last requirement: you want to be able to determine what to Show when
clicking button Show. Outcome could be either first name, name or country.
With current controls on the form there is no way to determine what to show when clicking
button Show. You will need some extra RadioButtons to get that job done.
Add three RadioButtons behind the three CheckBoxes. Next run the application and select
one of them. What happens and why? Try answering this for yourself before reading further.
49
7. Extending application TextPlay
You will probably have noticed that when clicking on one of the newly added RadioButtons
the RadioButton selected at lines group gets deselected.
Illustration 55: Selecting RadioButton 'Show' deselects
RadioButton '1 line'
Remember page 41: “Where all three CheckBoxes can be selected only one RadioButton can
at any given time. Keep that in mind.”
All RadioButtons act like this when being in the same container. And for a RadioButton that
makes sense as you only want one to be selected.
In this case your form is the container of the placed RadioButtons and since all the RadioButtons are in the same container only one can be selected.
So what you need is a separate container to hold your newly added RadioButtons.
First rename the RadioButtons to rbtShow1, rbtShow2 and rbtShow3. Next select them and
do ctrl+x (or right click and select cut in menu).
Illustration 56: ToolBox tab Container showing Frame
Next select the Tab container in the ToolBox and click on Frame. Drag a frame on the form
where the cut RadioButtons used to be and name it frmShow. Set the Text to “Show”.
50
7. Extending application TextPlay
Illustration 57: Frame Show placed on form
Now with the frame selected do ctrl+v (or right click and select paste in menu)
Illustration 58: RadioButtons pasted into Frame Show
Now run the application again and see what happens. You should be able to click the Show
RadioButtons independently from the one for lines.
Containers
Containers make it easy to manage controls that belong together. If you drag the frame over
the form all controls within the frame will be dragged along as they are in the container.
When for example you need certain controls visible under certain conditions, place them in one
container. Next you can make them visible or invisible just by setting the Visible property of the
container, instead of setting the Visible property of each individual control.
A Frame is a container with edges borders and a label.
More on Frame see http://gambasdoc.org/help/comp/gb.qt4/frame?v3
Back to design place the Line RadioButtons in their own frame as well. Name the Frame
fraLines with Text Lines
51
7. Extending application TextPlay
Consider it good practice to always place RadioButtons in their own container. In time you will
find out this has his advantages
When completed your result should look something like the illustration below.
Illustration 59: All RadioButtons placed in their Frames
Now let's recode the btnShow event click to meet our requirements (code see next page).
Illustration 60: RadioButtons show working as supposed
Now run and test the result. If all is well it should work.
52
7. Extending application TextPlay
Public Sub btnShow_Click()
If rbtShow1.Value Then
If IsNull(tbxFirstName.Text) Then
Message(“First fill in a first name”)
Else
Message(“The name entered is “ & tbxFirstName.Text)
Endif
Else
If rbtShow2.Value Then
If IsNull( tbxName.Text) Then
Message(“First fill in a name”)
Else
Message(“The name entered is “ & tbxName.Text)
Endif
Else
If IsNull( tbxCountry.Text) Then
Message(“First fill in a country”)
Else
Message(“The name entered is “ & tbxCountry.Text)
Endif
Endif
Endif
End
7.5 A last review of the application
In this last part of this chapter you are going to review your application and see if it can be
simplified and made more friendly in use.
7.5.1 Do you need a button Show?
That is a very good question. You have made an application where you first need to select
what to show and then click the button Show to make it show.
So, could you not simply select what to show and it shows? That is for you to figure out.
Start with deleting the button Show. Now think about the next three questions and see if you
can answer them:
- When do you want this to happen?
- Where do you want this to happen?
- Do I have usable code in my project I can simply copy/paste?
The answer to the first question will give you the event to code, the second one the object(s)
to code (read: controls). Take a moment to think about this and try to solve it yourself, before
continuing to the answer.
A positive answer to the third question will make for a quick redo to meet the new demands.
Think about this as well and solve it yourself, before going to the answer.
7.5.2 Could iSwitch format be more clear?
As you gave seen you have used the variable iSwitch to be set accordingly to selections
made in the add CheckBoxes to determine what needs to be show in the Label and TextArea.
These are the values of iSwitch and what they represent:
Value
Represents
1
first name → 1 line
53
7. Extending application TextPlay
12
first name and name → 1 or 2 lines
2
name → 1 line
23
name and country → 1 or 2 lines
123
first name, name and country → 1, 2 or 3 lines
If you would add a next field the Value of iSwitch would get more complicated. So thinking
about these values and their format is something that can make life easier in a later stage of
development when things need to be added or changed.
So here are some more questions to think about:
- What format could do better?
- Can the current variables type (Integer) hold the improved format?
The answer to the first question will determine the outcome of the second. Again, think about
this as well and solve it yourself, before going to the answer.
7.5.3 Should the button Add be enabled if no Add is checked?
Again, good question. Should it be enabled or would it be better to enable it when a Add gets
checked and disabled when no Add is checked?
Again think about the next two questions and see if you can answer them:
- When do you want this to happen?
- Where do you want this to happen?
The answer to the first question will give you the event to code, the second one the object to
code. Take a moment to think about this and try to solve it yourself, before continuing to the
answer.
7.5.4 Should the button Clear be enabled if there is nothing to clear?
The questions keep coming. Wouldn't it be better to have button Clear enabled when TextArea and Label have content and have it disabled when no content present?
And again think about the next two questions and see if you can answer them:
- When do you want this to happen?
- Where do you want this to happen?
The answer to the first question will give you the event to code, the second one the object to
code. Take a moment to think about this and try to solve it yourself, before continuing to the
answer.
7.6 Answers to the last review
Here you will find all answers to the questions posed in 7.5. Make sure that you have first
tried to solve the answers yourself and don't be afraid of failure. There is no such thing as failure, only lessons to be learned.
And discovering how to do these thing yourself by failing and trying all over again is the method with the biggest learning curve that sticks the longest.
This is one of the main reasons I choose to start examples with code that can be improved
and show you the improvements step by step. In this way they will make more sense.
So after you tried and succeeded or not have a look at how I did it and keep in mind that
there are other possibilities as well. You might have solved it differently and have it working
just as well.
7.6.1 Do you need a button Show?
Judging the illustration on the next page I would say you don't.
54
7. Extending application TextPlay
Illustration 61: No button Show but still doing the same
job
The questions and their answers:
- When do you want this to happen?
→ As soon as one of the RadioBoxes in Frame show is clicked → RadioBoxes Click event
- Where do you want this to happen?
→ On rbtShow1, rbtShow2 and rbtShow3
- Do I have usable code in my project I can simply copy/paste?
→ parts of the btnShow code are usable
Code example:
Public Sub rbtShow1_Click()
If IsNull(tbxFirstName.Text) Then
Message(“First fill in a first name”)
Else
Message(“The first name entered is “ & tbxFirstName.Text)
Endif
End
Public Sub rbtShow2_Click()
If IsNull(tbxName .Text) Then
Message(“First fill in a name”)
Else
Message(“The name entered is “ & tbxName.Text)
Endif
End
55
7. Extending application TextPlay
Public Sub rbtShow3_Click()
If IsNull( tbxCountry .Text) Then
Message(“First fill in a country”)
Else
Message(“The country entered is “ & tbxCountry.Text)
Endif
End
Code, run and test is all that is left.
7.6.2 Could iSwitch format be more clear?
It sure can be more clear. Let's look at the questions and their answers:
- What format could do better?
→ Example:
100 → first item needs to be shown
110 → first and second item need to be shown
111 → all items need to be shown
001 → third item needs to be shown
101 → first and third item needs to be shown
….
- Can the current variables type (Integer) hold the improved format?
→ No it can't, you would need a String, because in Integer 001 would become 1. You want it
to remain 001, hence a String and in code quote “001”!!
Feel free to adapt your code to meet the new requirements. Make sure to change iSwitch into
String and adapt all 1, 12, 2, 23, 13 and 123 values accordingly. Change the iSwitch -1 value
to “000”, indicating nothing to be shown.
7.6.3 Should the button Add be enabled if no Add is checked?
No it should not be enabled. Again let's have a look at the questions and answers:
- When do you want this to happen?
→ When form opens, no Add is checked so button should be disabled → Form open event
→ When one of the Add gets checked button should be enabled → CheckBox Click event
→ When all Adds get deselected the button should disable → CheckBox Click event
- Where do you want this to happen?
→ On Fmain and cbxFirstName, cbxName and cbxCountry
Code to disable the button Add on opening the form:
Public Sub Form_Open()
Me.Center
btnAdd.Enabled = False
End
Code to enable disable button Add when clicking cbxFirstName, cbxName or cbxCountry:
As you will notice in code below, you can run code from one routine (being
cbxFirstName_Click) from another routine (being cbxName_Click and cbxCountry_Click).
56
7. Extending application TextPlay
Public Sub cbxFirstName_Click()
If (cbxFirstName.Value = 0) And (cbxName.Value = 0) And (cbxCountry.Value = 0) Then
btnAdd.Enabled = False
Else
btnAdd.Enabled = True
Endif
End
'– Since code for other checkboxes is same use cbxFirstName_Click routine to do the job -Public Sub cbxName_Click()
cbxFirstName_Click
End
Public Sub cbxCountry_Click()
cbxFirstName_Click
End
You will get to see more of this further in the guide. For now just knowing that it is possible will
do.
7.6.4 Should the button Clear be enabled if there is nothing to clear?
No it should not be enabled. And again let's have a look at the questions and answers:
- When do you want this to happen?
→ When form opens, no content so button should be disabled → Form open event
→ When Text is Added button should be enabled → btnAdd Click event
→ When Text is Cleared button should be disabled → btnClear Click event
- Where do you want this to happen?
→ On Fmain and btnAdd and btnClear
Code to disable the button Clear on opening the form:
Public Sub Form_Open()
Me.Center
btnAdd.Enabled = False
btnClear.Enabled = False
End
Add this code to the btnAdd_Click event:
57
7. Extending application TextPlay
Public Sub btnAdd_Click()
….
…..
Endif
'– Add this line at the end of the routine
btnClear.Enabled = True
End
Add this code to the btnClear_Click event:
Public Sub btnClear_Click()
….
…..
tarResult.Clear
'– Add this at the end of the routine
'– You need to set the focus to another control before disabling btnClear as it has the focus
btnAdd.SetFocus
btnClear.Enabled = False
End
Since btnClear has the focus when being clicked and you can't disable a control that has the
focus you need to set the focus to another control before disabling btnClear.
You will notice that upon clicking clear, the Adds are deselected by code resulting in the Add
button being disabled as well. In this example that is just perfect.
You probably didn't expect that to happen, but you did code for it. But it is a good demonstration of event driven programming. One event can trigger a next event, that can trigger a next
event. So keep your mind to it not to end up with unwanted side effects coming from parts of
could you would never look for.
Now close the project in menu File → Quit. This will also close Gambas and set you at the
point to start for the next chapter.
58
8. Your second application: TextPlayT(w)o
8 Your second application: TextPlayT(w)o
8.1 What will be done in this chapter
Main focus will be string functions, for that you will built a new application.
This will involve
➢ Opening Gambas IDE and make a new project
➢ Make a main form
➢ Place fourteen controls on the form (1 TextArea, 5 TextBoxes, 2 buttons, 1 frame, 2
RadioButtons, 1 ValueBox, 2 labels)
➢ Make a search and replace form
➢ Place four controls on the form (2 TextBoxes, 2 buttons)
➢ Write some code
➢ Run the application from Gambas IDE
You can learn about:
➢ Working with the Gambas IDE
➢ Working with more than one form
➢ How to interact between forms
➢ Meaning of Subroutines, Public and Private
➢ Working with numbers
➢ Working with String functions to search and replace text
➢ Working with String functions to split text and more
➢ User interaction (input from user, output from application)
8.2 Start a new project and design the first form
Open Gambas3 IDE and start a new graphical application project named TextPlayT(w)o.
Right click Fmain and select Rename.. in the menu and name it FrmMain.
Place following controls on FrmMain with some properties pre-set:
1 TextArea: Name → txaContent; Text → empty
1 Label: Text → Split character; Alignment → Right
1 TextBox: Name → tbxSplit ; Text → empty
1 Label: Text → Number of splits; Alignment → Right
1 ValueBox: Name → vbxSplit
1 Button: Name → btnSplit; Text → Split
4 TextBoxes: Name → tbxLine1...tbxLine4; Text → empty; ReadOnly → True
1 Frame: Name → fraSearch; Text → Search or Search/Replace; Enabled → False
1 RadioButton (in fraSearch): Name → rbtSearch; Text → Search
1 RadioButton (in fraSearch): Name → rbtReplace; Text → Search/Replace
1 Button: Name → btnSearch; Text → Search; Enabled → False
When finished with placing all controls and setting all properties accordingly you should have
something like in the illustrations on the next page.
First illustration (62) shows the form in the IDE designer.
Second illustration (63) shows the form when run.
59
8. Your second application: TextPlayT(w)o
Illustration 62: Main form in IDE design mode
Illustration 63: Main form when run from IDE
8.3 Playing with text the other way around
In TextPlay(w)o you are going to start with doing the opposite of TextPlay. In TextPlay you had
input in TextBoxes and it was put together in a TextArea.
In this example you will get your input in the TextArea (one big string) and need to split it to fit
in the TextBoxes (several strings).
8.3.1 Some first coding to split the text
You start with some code to make FrmMain centre upon opening.
60
8. Your second application: TextPlayT(w)o
Public Sub Form_Open()
Me.Center
End
Step 1: Focus on splitting the text
What you need to accomplish is split entered text in the TextArea (txaContent) into the TextBoxes (tbxLine1 to tbxLine4). For that you need to know on what character to split.
Example:
txaContent.Text → “split this text on space”
tbxSplit.Text → “ “ (a space)
Pressing Split should result in:
tbxLine1.Text → “split”
tbxLine2.Text → “this”
tbxLine3.Text → “text”
tbxLine4.Text → “on”
So input is the text entered in txaContent and the character entered in tbxSplit. The splitting
needs to take place when btnSplit is clicked.
For splitting strings you can use the function Split().
StringArray = Split(String As String [, Separators As String, Escape As String, ...])
Split enables you to split a string using the Separator to determine where to Split the string.
String is the string to split
Separators are the characters used to split the text. By default the seperators are not returned.
StringArray is an array of strings into where the results of Split are returned. So it contains all
the splitted string results as separate strings in one array of strings.
Split has more options than mentioned above.
Split is a String Function. String functions are functions that can be used to do work with
Strings.
More on Split see http://gambasdoc.org/help/lang/split?v3
Overview of String Functions see: http://gambasdoc.org/help/cat/string?v3
As the splitting needs to take place when btnSplit is clicked you will start with coding this
event:
Public Sub btnSplit_Click()
Dim sSplit As String[]
'String followed by [ and ] declares a string array
Dim sText As String
Dim iX As Integer
iX = 1
' Used to determine what txbLine to output to
sSplit = Split(txaContent.Text, tbxSplit.Text)
For Each sText In sSplit
Select iX
Case 1
tbxLine1.Text = sText
Case 2
tbxLine2.text = sText
61
8. Your second application: TextPlayT(w)o
Case 3
tbxLine3.Text = sText
Case 4
tbxLine4.Text = sText
End Select
iX = iX + 1
Next
End
For Each Variable In Expression Next
Repeats a loop while enumerating the object in expression
Expression must be a reference to a enumerable object like a collection or an array
Variable is the reference to the item in the enumerable object in Expression
In above code sText (variable) stands for each string item in the string array sSplit (expression)
More on For Each see http://gambasdoc.org/help/lang/foreach?v3
Now run the application and:
1. in txaContent type: Split.On.Dot.Please
1. in tbxSplit type: .
3. click btnSplit
Illustration 64: Text splitted on the dot (.)
It runs as expected, but try again with some other text in txaContent en Split on “\n” (line
feed).
Run the application and:
1. in txaContent type:
This is Line 1
Next line aka as line 2
62
8. Your second application: TextPlayT(w)o
Line 3 above is empty and this is line 4
1. in tbxSplit type: \n
3. click btnSplit
Illustration 65: Result of splitting on \n
Now this makes sense as “ Separators are the characters used to split the text” So Split will
check for both “\” and “n” to split and that is exactly what happened.
Step 2: Improve splitting the text
What you want is it to split on a line feed (“\n”) instead. So you need to code the btnSplit
event to recognize the “\n” and act accordingly. For this you need to add an extra “\”15.
So back to IDE for some recoding:
Public Sub btnSplit_Click()
Dim sSplit As String[]
'String followed by [ and ] declares a string array
Dim sText As String
Dim iX As Integer
iX = 1
' Used to determine what txbLine to output to
Select tbxSplit.Text
Case “\\n”
' To check for a line feed
tbxSplit.Text = Chr(10) ' To split on a line feed (=Chr(10))
End Select
sSplit = Split(txaContent.Text, tbxSplit.Text)
For Each sText In sSplit
Select iX
Case 1
tbxLine1.Text = sText
Case 2
tbxLine2.text = sText
Case 3
tbxLine3.Text = sText
15
The extra “\” makes sure the following “\” is preserved.
63
8. Your second application: TextPlayT(w)o
Case 4
tbxLine4.Text = sText
End Select
iX = iX + 1
Next
End
Chr(Code As Integer) As String
Returns the character for the Code (with Code being the ASCII code)
Code needs to be a Integer value from 0 to 255
In above code Chr(10) stands for a line feed.
More on Chr() see http://gambasdoc.org/help/lang/chr?v3
Overview of String Functions see: http://gambasdoc.org/help/cat/string?v3
Now run the application again and do the same test as done before.
Illustration 66: Renewed result of splitting on "\n"
Seems you have a perfect split on “\n” or a line feed.
Note that once clicking btnSplit the content of tbxSplit contains Chr(10). Because TextBoxes
are single line they represent it with this symbol instead of going to a new line.
8.3.2 Determine the number of splits
Now that the split works as needed focus is on the numbers of splits you want.
Step 1: Implement to take number of splits into account
As you have 4 lines to show the splitted strings it would be great if you entered 2 in number of
splits and only 2 where shown, or enter 1 and only one is shown.
So you will again need to recode btnSplit event to make that happen:
64
8. Your second application: TextPlayT(w)o
Public Sub btnSplit_Click()
Dim sSplit As String[]
'String followed by [ and ] declares a string array
Dim sText As String
Dim iX, iNumSplits As Integer
iX = 1
' Used to determine what txbLine to output to
iNumSplits = vbxSplit.Value ' Used to determine number of splits
Select tbxSplit.Text
Case “\\n”
' To check for a line feed
tbxSplit.Text = Chr(10) ' To split on a line feed (=Chr(10))
End Select
sSplit = Split(txaContent.Text, tbxSplit.Text)
For Each sText In sSplit
If iX <= iNumSplits Then
Select iX
Case 1
tbxLine1.Text = sText
Case 2
tbxLine2.text = sText
Case 3
tbxLine3.Text = sText
Case 4
tbxLine4.Text = sText
End Select
iX = iX + 1
Endif
Next
End
Now check if it works by running the application
Illustration 67: Result of splitting on "\n" showing 2 lines
65
8. Your second application: TextPlayT(w)o
You will notice that when showing 4 lines and next trying 2 lines that lines 3 and 4 are still
filled. The reason behind this is that the tbxLine variables aren't cleared before a new split.
Step 2: Recode to make tbxLine variables clear
To do this you need to code the btnSplit event again:
Public Sub btnSplit_Click()
Dim sSplit As String[]
'String followed by [ and ] declares a string array
Dim sText As String
Dim iX, iNumSplits As Integer
iX = 1
' Used to determine what txbLine to output to
iNumSplits = vbxSplit.Value ' Used to determine number of splits
ClearLines
'This starts a subroutine
Select tbxSplit.Text
Case “\\n”
' To check for a line feed
tbxSplit.Text = Chr(10) ' To split on a line feed (=Chr(10))
End Select
sSplit = Split(txaContent.Text, tbxSplit.Text)
For Each sText In sSplit
If iX <= iNumSplits Then
Select iX
Case 1
tbxLine1.Text = sText
Case 2
tbxLine2.text = sText
Case 3
tbxLine3.Text = sText
Case 4
tbxLine4.Text = sText
End Select
iX = iX + 1
Endif
Next
End
Private Sub ClearLines()
tbxLine1.Clear
tbxLine2.Clear
tbxLine3.Clear
tbxLine4.Cear
End
As you can see in the code above the code for clearing the lines is taken into a separate
routine (Public Sub ClearLines()). This separate routine is a subroutine (indicated by the Sub).
It is a Private routine (indicated by Private).
The fact that the routine is a subroutine and Private means that it can be called anywhere
within the same class it resides to be executed.
The class subroutine ClearLines() resides in the form class of FrmMain (the tab in IDE named
FrmMain.Class). So anywhere in the code of FrmMain you can use subrourine ClearLines().
66
8. Your second application: TextPlayT(w)o
You call the routine simply by its name to be executed (in our code you simply write
ClearLines).
Upon execution the interpreter after executing the line 'iNumSplits = vbxSplit.Value' will run
the subroutine ClearLines and execute it line by line before continuing with the execution of
'Select tbxSplit.Text'
[Static] {Public | Private} {Procedure | Sub} Identifier(Parameter As Datatype.....)
Identifier is the name of the subroutine or procedure
Parameter is/are values that can be passed to the subroutine/procedure when calling it. You
have to declare a data type for each parameter used.
A subroutine or procedure does not return any values. Use a function for that.
More on Sub see http://gambasdoc.org/help/lang/sub?v3
Private
Keyword that declares accessibility of a method (sub/procedure or function), variable or
property
A Private declared method, variable or property can NOT be used outside its own class.
More on Private see http://gambasdoc.org/help/lang/private?v3
Public
Keyword that declares accessibility of a method (sub/procedure or function), variable or
property
A Public declared method, variable or property can be used outside its own class.
More on Private see http://gambasdoc.org/help/lang/public?v3
Now run the application again and first let it split showing 4 lines
Illustration 68: Split for 4 lines
Next split again for 1 line and see if lines 2 to 4 are cleared (see illustration on next page).
67
8. Your second application: TextPlayT(w)o
Illustration 69: Next a split for 1 line (other lines are now cleared)
Seems that all is working as expected.
8.4 Search for text
For this part you first need to make a new form. The new form is going to serve as a window
to enter the search string.
8.4.1 Make a new form
To make a new form in the Project Browser right click Sources. In the menu select New →
Form.
Illustration 70: Ad a new form to the project
68
8. Your second application: TextPlayT(w)o
Name the form FrmSearchReplace.
Illustration 71: Dialog to name the form
Place following controls on FrmSearchReplace with some properties pre-set:
1 TextBox: Name → tbxSearch ; Text → Enter a string to search...
1 Button: Name → btnSearch; Text → Search
Illustration 72: FrmSearchReplace with controls placed
69
8. Your second application: TextPlayT(w)o
Now add some initial code to the form open event (right click the form and select menu Event
→ Open)
Public Sub Form_Open()
Me.Caption = “Search”
End
This will give the FrmSearchReplace the caption “Search”. As you notice FrmSearchReplace
is not centered, FrmMain is. Idea is that FrmSearchReplace gets opened when clicking the
btnSearch in FrmMain. To make sure that FrmSearchReplace is not in front of txaContent,
you leave all default, meaning in top left of your screen
8.4.2 Make FrmSearchReplace open from btnSearch on FrmMain
Double click FrmMain in the Project Browser and next select btnSearch.
As you might remember btnSearch was disabled. So in btnSearch properties set enabled to
True. Next right click the selected btnSearch and in the menu select Event → Click.
This will open the Tab FrmMain.class ready to code the click event of btnSearch.
Public Sub btnSearch_Click()
FrmSearchReplace.Show
End
What you do here is call the method Show of FrmSearchReplace. So you tell the FrmSearchReplace to show itself.
Forms inherit the Window class which means properties, methods and events are inherited
from the window class every time a form is made.
Forms
The Form class inherits the Window class. This means that properties, methods (routines) and
events of the Windows class (parent class to the form class) are inherited from the window
class every time a form is made.
This also means that you can use these in your forms.
Sub Show()
Shows the window
More on Forms see http://gambasdoc.org/help/comp/gb.qt4/form?v3
More on Show see http://gambasdoc.org/help/comp/gb.qt4/window/show?v3
Now run the application and click the btnSearch.
You should see something like the illustration on the next page. Notice the window caption of
FrmSearchReplace stating Search.
70
8. Your second application: TextPlayT(w)o
Illustration 73: FrmSearchReplace opened from btnSearch
Seems you now have an application consisting of two forms. And from within one form you
can open the other.
Now the real challenge is to enter a search string in the FrmSearchReplace and search for
the string in txaContent on FrmMain.
This will require some interaction between the two forms and brings us to a next level.
8.4.3 Project intermezzo: Form class interaction explained
You already had a first glimpse at Private and Public declarations. With two forms at hand this
is going to start making sense.
The requirement of having to search a string entered in a TextBox on one form to be
searched in a TextArea on another form and then have the result selected in that TextArea requires you to understand the difference in Private and Public.
They are the basis of what will and will not be available to other Form classes to use in their
code.
By default coded events (named subs, procedures or methods) of controls you draw on a
form are Public.
So in our project what can one form use from the other?
Let's make an overview and see what is available and what is not.
Public in FrmSearchReplace are:
Methods
Form_Open
Private in FrmSearchReplace are:
Methods
Public in FrmMain are:
Methods
Form_Open
71
8. Your second application: TextPlayT(w)o
btnSplit_Click()
btnSearch_Click
Private in FrmMain are:
Methods
ClearLines()
So Public means available to other forms, Private means NOT available to other forms.
Let's give this a go in the IDE. Double click FrmSearchReplace in the Project Browser.
Now double click btnSearch. This will open a btnSearch_Click() method in the FrmSeachReplace.class (= all the code for the form).
Write the following code to the btnSeach click event:
Public Sub btnSearch_Click()
FrmMain.btnSplit_Click
End
Next run the application.
In txaContent type: To be or not
In tbxSplit type: “ “ (a space)
In vbxSplit type: 4
Next click btnSearch to open FrmSearchReplace. In FrmSearchReplace click btnSearch and
see what happens in FrmMain.
Illustration 74: Running btnSplit code from btnSearch on another form
What actually happened upon clicking btnSearch on the Search form is that code from another form class got called by the current form Class and executed before returning.
So you can directly call Public methods from another class to be executed.
Indirectly the Private method ClearLines got called as well. With this difference that it was
called from a method (btnSplit_Click()) within its own class.
72
8. Your second application: TextPlayT(w)o
Illustration 75: Interaction between methods in different form classes
You can now remove the code from btnSearch in FrmSearchReplace class as it was just an
example.
Back to our problem to solve in this project.
There are two possible approaches:
1. Code the searching on form FrmSearchReplace
2. Code the searching on form FrmMain
In both approaches it comes down to get the string that needs to be searched and perform a
search. The code for searching will not be that different. What it comes down to is what is the
best approach in getting the string and next selecting it when found.
Let's have a look at both approaches and see what fits best.
1. Code the searching on form FrmSearchReplace
So what you need to get is the content from txaContent.Text. This means declaring a Public
variable as String and make sure every time txaContent.Text is changed the string is passed
to the variable.
Next search can be performed and then somehow the result has to be selected in txaContent
while it isn't even Public!!
All in all a tough road to walk that requires a lot of extra coding.
2. Code the searching on form FrmMain
What you need here is pass the string to be searched from FrmSearchReplace to FrmMain,
perform the search and select the result in txaContent.
As all takes place on FrmMain this is a much easier approach. All that needs to be done is
pass a string from one form to another, nothing more.
What you need is a method (sub or procedure) on FrmMain that can pass an argument, perform the search and select the result.
8.4.4 Back on track to code a Public method on FrmMain
First check out how passing arguments in a methods works.
73
8. Your second application: TextPlayT(w)o
In FrmMain class write following code:
Public Sub SearchString(StringToSearch As String)
Message(StringToSearch)
End
StringToSearch is a string value that gets passed to the method upon calling it.
In FrmSearchReplace class write following code:
Public Sub btnSearch_Click()
FrmMain.SearchString(tbxSearch.Text)
End
Now run the application, click btnSearch on FrmMain, write your name in the search field and
click btnSearch. You should see your name appear in a message box.
So the Text property of tbxSearch (although not being Public) is passed to another class as
an argument (StringToSearch) to be used in a Public method in that other class.
So passing arguments is one way of passing Private data to another Class. Keep that in
mind!
Illustration 76: Search string passed as argument of a Public method
I hope this makes clear how passing arguments works. Now that you have seen it working
you know the search string can reach method SearchString in FrmMain all you need to do is
code for it to be found.
8.4.5 Lets search some string
Search a string and select it in tarContent when found is the mission to complete.
For that you need to code the method SearchString in FrmMain class:
74
8. Your second application: TextPlayT(w)o
Public Sub SearchString(StringToSearch As String)
Dim iB, iL As Integer
iB = 1
iB = InStr(tarContent.Text, StringToSearch, iB) 'Determines the start position of string found
iL = Len(StringToSearch)
'Determines length of the string
If iL > 0 Then
tarContent.Select(iB - 1, iL)
'Select the found string only when length > 0
Endif
End
Position = Instr(String As String , Substring As String [, Start As Integer, ...])
Instr enables you to search a string to determine its start position.
Position is the start position of the string found (0 when nothing found)
String is the string value that will be searched
SubString is the string value that you are searching for
Start is the position you want the search to begin
Instr has more options than mentioned above.
Instr is a String Function. String functions are functions that can be used to do work with
Strings.
More on Instr see http://gambasdoc.org/help/lang/instr?v3
Overview of String Functions see: http://gambasdoc.org/help/cat/string?v3
Length = Len(Args As String)
Len enables you to determine the length of a string
Length is the length of the string in arguments Args (0 when empty)
Args is the string value you want to determine the length of
Lenght is determined by byte count of the string. ASCII characters take up one byte.
Characters like ü or é (UTF-8) take up two bytes and thus will count for two!!
Len is a String Function. String functions are functions that can be used to do work with
Strings.
More on Len see http://gambasdoc.org/help/lang/len?v3
Overview of String Functions see: http://gambasdoc.org/help/cat/string?v3
Now run the application and do some testing.
In txaContent write:
I am looking for my name
Have you seen my name
It is Willy they tell me
Please search for my name
Next click btnSearch on the main form to open the Search form.
In the Search form type “Willy” (without the quotes) and click Search.
Willy should be selected in txaContent on the main form.
75
8. Your second application: TextPlayT(w)o
Illustration 77: Seems like search performs as expected
All should work as expected and select the searched string when found, select nothing when
nothing is found.
8.5 Search and replace text
Before you can start searching and replacing string you will need to add some controls to you
current FrmSearchReplace.
8.5.1 Prepare the forms for Search and Replace
In the IDE click FrmSearchReplace in the Project Browser.
Place following controls on FrmSearchReplace with some properties pre-set:
1 TextBox: Name → tbxReplace ; Text → Enter the replace string...
1 Button: Name → btnReplace; Text → Replace
Fastest method is to select tbxSearch and btnSeach, copy and paste them onto the form,
drag them to the proper location and adapt the properties Name and Text.
Illustration 78: Replace TextBox and Button added to FrmSearchReplace
Next click FrmMain in the Project Browser
Select fraSearch and set the property Enabled to True
76
8. Your second application: TextPlayT(w)o
Illustration 79: FrmSearch property Enabled set to true on FrmMain
With the frame for choosing between Search and Search/Replace enabled and FrmSearchReplace prepared for Replacing you are set for the next step.
8.5.2 Making FrmSearchReplace appear depending on selection in FrmMain
When clicking button Search on FrmMain you want FrmSearchReplace to appear different
depending on what was selected in the fraSearch (a Frame).
When Search is selected FrmSearchReplace has to:
- have caption Search
- show search field
- show search button
When Search/Replace is selected FrmSearchReplace has to:
- have caption Search and Replace
- show search and replace fields
- show search button
- show replace button
You will start with FrmMain to get the fraSearch and RadioButtons to work:
' -- Used to determine how FrmSearchReplace is shown 1=search, 2=replace -Public SearchReplace As Byte
Public Sub Form_Open()
Me.Center
rbtSearch.Value = True
rbtSearch_Click
End
You use Public to declare a variable SearchReplace to pass a value to FrmSearchReplace to
determine whether to search or to search and replace.
rbtSearch is set to True so it is the default selection upon opening FrmMain. Next you execute the rbtSearch click event. This is the next step you need to code.
Clicking on one of the RadioButtons has to set SearchReplace to value 1 or 2, that is all.
77
8. Your second application: TextPlayT(w)o
Datatypes
Datatypes determine the type of data a variable can contain when declared. The datatype also
determines the length of the space used by the data.
Gambas native datatypes are:
Type
Boolean
Byte
Short
Integer
Long
Single
Float
Date
String
Variant
Object
Pointer
Description
True or False
0 to 255
-32.768 to 32.767
-2.147.483.648 to 2.147.438.647
-9.223.372.036.854.775.808 to 9.223.372.036.854.775.807
single precision floating-point type
double precision floating-point type
Date and time each stored in an Integer
A variable length string of characters
Any datatype
Anonymous reference to any object
A memory address
Default value
False
0
0
0
0
0.0
0.0
Null
Null
Null
Null
0
More on datatypes see http://gambasdoc.org/help/cat/datatypes?v3
More on Floating Point Numbers: http://gambasdoc.org/help/cat/float?v3
More on single precision floating-point format:
https://en.wikipedia.org/wiki/Single_precision_floating-point_format
More on double precision floating point format:
https://en.wikipedia.org/wiki/Double_precision_floating-point_format
Code for event click of rbtSearch:
Public Sub rbtSearch_Click()
SearchReplace = 1 'search
End
Code for event click of rbtReplace:
Public Sub rbtReplace_Click()
SearchReplace = 2 'replace
End
With this code in place you have your means to know what FrmSearchReplace has to show
upon opening. If FrmMain Public variable SearchReplace is 1 it's a search, when 2 it's a replace.
Now let's make that happen. For this you need to code the Open event of FrmSearchReplace:
Public Sub Form_Open()
Select FrmMain.SearchReplace
Case 1
78
8. Your second application: TextPlayT(w)o
Me.Caption = "Search"
btnReplace.Visible = False
tbxReplace.Visible = False
Case 2
Me.Caption = "Search and Replace"
btnReplace.Visible = True
tbxReplace.Visible = True
End Select
End
Now run the application and see if all reacts as wanted
Illustration 80: Search shown when search selected
Illustration 81: Search and Replace shown when search/replace selected
79
8. Your second application: TextPlayT(w)o
8.5.3 Replace searched strings
To replace a string you again will write a Public method for FrmMain that does all the replacing.
In FrmMain write following code:
Public Sub ReplaceString(StringToReplace As String, StringToReplaceWith As String)
txaContent.Text = Replace(txaContent.Text, StringToReplace, StringToReplaceWith)
End
Now all that you need to do is run above code when button Replace is clicked.
In FrmSearchReplace write following code:
Public Sub btnReplace_Click
FrmMain.ReplaceString(tbxSearch.Text, tbxReplace.Text)
End
Again all you do is pass some arguments (being the search and replace strings) to the method ReplaceString to be dealt with accordingly.
Result = Replace(String As String, Pattern As String, ReplaceString As String[, ...])
Replace enables you to search a string and replace it with another string.
Result is the outcome of String with Pattern replaced by ReplaceString
String is the string value that will be searched
Pattern is the string value that you are searching for
ReplaceString is the string value that Pattern will be replaced by
Replace has more options than mentioned above.
Replace is a String Function. String functions are functions that can be used to do work with
Strings.
More on Replace see http://gambasdoc.org/help/lang/replace?v3
Overview of String Functions see: http://gambasdoc.org/help/cat/string?v3
Now run the application for some testing
In txaContent write:
Try to replace Willy
with silly if you can
First search for it, next click Replace
So go ahead type above lines, next type Willy in Search field and click button Search. If that
works type silly in the Replace field and click button Replace.
If all is well Willy should now be silly (see illustrations on the next page).
Play with it for a while and see what can and can't be done.
The RadioButtons in this example are placed on FrmMain to explain interaction between forms
and Public variables and how to deal with these situations.
It would be better practice to place them on FrmSearchReplace.
80
8. Your second application: TextPlayT(w)o
Illustration 82: Search still works well
Illustration 83: Replace does a good job as well
In this chapter you have worked with several String functions. You have noticed by now that a
lot is possible using String functions.
You will come to learn that they can be useful in a lot of situations, like importing a comma
delimited file, extracting returned information from a linux command run or building a text editor
just to mention a few examples.
They are very powerful tools to use and some of them you will be using a lot when working
with text based information, so get familiar with them.
Now in Gambas IDE click menu File → Quit. This gets you ready for the next chapter.
81
9. Your third application: NumPlay
9 Your third application: NumPlay
9.1 What will be done in this chapter
Main focus will be numerical data, for that you will built a new application.
This will involve
➢ Opening Gambas IDE and make a new project
➢ Make a main form
➢ Place a number of controls on the form
➢ Write some code
➢ Run the application from Gambas IDE
You can learn about:
➢ Working with the Gambas IDE
➢ Working with numeric data, date and time
➢ Error handling
➢ Working with Arithmetical functions and Date & Time functions
➢ Working with Localization and Translation functions
➢ Transfer numeric data in strings to numerical data types
➢ User interaction (input from user, output from application)
➢ Enumeration
9.2 Start a new project and design a form
Open Gambas3 IDE and start a new graphical application project named NumPlay.
Rename form FMain to FrmMain. Do this by right clicking FMain in the Project Browser and
next click Rename.
Place following controls on FrmMain with some properties pre-set:
1 ValueBox: Name → vbxNum1
1 ValueBox: Name → vbxNum2
1 Label: Name → lblOperator ; Text → empty; Alignment → Right
1 Separator
1 ValueBox: Name → vbxResult
1 Label: Name → lblResult ; Text → empty; Alignment → Right
1 Button: Name → btnCalc; Text → Calculate
1 Frame: Name → fraOperator; Text → Operator
1 RadioButton (in fraOperator): Name → rbtAdd; Text → +
1 RadioButton (in fraOperator): Name → rbtSubtract; Text → 1 RadioButton (in fraOperator): Name → rbtMultiply; Text → *
1 RadioButton (in fraOperator): Name → rbtDivide Text → /
1 RadioButton (in fraOperator): Name → rbtPower Text → ^
When finished with placing all controls and setting all properties accordingly you should have
something like in the illustrations on the next page.
First illustration (84) shows the form in the IDE designer.
Second illustration (85) shows the form when run.
82
9. Your third application: NumPlay
Illustration 84: FrmMain after placing all controls
Illustration 85: FrmMain when run
9.3 Doing the maths
In NumPlay you are going to work with numbers and calculations. Along the road you'll also
have a look at numerical data shown in text based controls and in using input from text based
controls for calculations.
83
9. Your third application: NumPlay
9.3.1 Analyse the needs and determine a strategy
Based on the operator clicked you need to do some things.
To begin with lblOperator needs to show the calculation operation to be done when clicking
btnCalc. Lets start by doing this first.
You know that each RadioButtons text property holds the operation. This only needs to put
placed in the lblOperator text property. For this you need to code the Click event of each RadioButton:
Public Sub Form_Open()
Me.Center
rbtAdd_Click
'To ensure lblOperator shows +
End
Public Sub rbtAdd_Click()
lblOperator.Text = rbtAdd.Text
End
Public Sub rbtSubtract_Click()
lblOperator.Text = rbtSubtract.Text
End
Public Sub rbtMultiply_Click()
lblOperator.Text = rbtMultiply.Text
End
Public Sub rbtDivide_Click()
lblOperator.Text = rbtDivide.Text
End
Public Sub rbtPower_Click()
lblOperator.Text = rbtPower.Text
End
Now run the application and see what happens when clicking the RadioButtons.
Illustration 86: lblOperator shows selected Operator
84
9. Your third application: NumPlay
Next challenge is to make the calculations based on the selected operator.
So when clicking btnCalc you need to perform the selected operation on the values entered in
vbxNum1 and vbxNum2 and return the result in vbxResult.
Clearly the Operation selection is centrally crucial in all that needs to happen. Somehow
when clicking btnCalc you need to determine what RadioButton is selected and act accordingly.
There are several possible approaches, one of them is using a switch that is set when a RadioButton is clicked.
This is how the switch value could represent the Operator
Operator:
+
*
/
^
Switch value:
0
1
2
3
4
To implement this some code needs to be added:
Private iSwitch As Integer
Public Sub Form_Open()
Me.Center
rbtAdd_Click
'To ensure lblOperator shows +
End
Public Sub rbtAdd_Click()
lblOperator.Text = rbtAdd.Text
iSwitch = 0
End
Public Sub rbtSubtract_Click()
lblOperator.Text = rbtSubtract.Text
iSwitch = 1
End
Public Sub rbtMultiply_Click()
lblOperator.Text = rbtMultiply.Text
iSwitch = 2
End
Public Sub rbtDivide_Click()
lblOperator.Text = rbtDivide.Text
iSwitch = 3
End
Public Sub rbtPower_Click()
lblOperator.Text = rbtPower.Text
iSwitch = 4
End
Public Sub btnCalc_Click()
85
9. Your third application: NumPlay
Print iSwitch
End
Print iSwitch will be executed when clicking on btnCalc giving us the current value of iSwitch
during run time. This will help you check if all works as expected.
Run the application, select subtract and next click btnCalc. If you pay attention in the console
output of the IDE you will see 1 appear when clicking btnCalc
Illustration 87: Console output in IDE
Using the Print instruction will output to the IDE console during runtime. It is a way of checking what is happening during runtime and comes in handy when something is not working as
expected to help you investigate what is actually happening.
Print instruction is typically used to output to the user in a command line Gambas application. A
simple Print followed by a string will output to the standard output (in IDE being the console, in
a command line application being the terminal it runs in).
Print can also used to output to Streams.
Streams are internal objects that Gambas creates for manipulating files, processes, sockets,
and many other objects that can be used as files.
More on Print see http://gambasdoc.org/help/lang/print?v3
Click another operator and next on btnCalc to see if all the Switch values meet your requirements.
Now that you have ensured yourself that iSwitch holds the proper value next step is to code
for the calculations based on iSwitch.
For this you need to code the Click event of btnCalc:
86
9. Your third application: NumPlay
Public Sub btnCalc_Click()
Select iSwitch
Case 0
vbxResult.Value = vbxNum1.Value + vbxNum2.Value
Case 1
vbxResult.Value = vbxNum1.Value – vbxNum2.Value
Case 2
vbxResult.Value = vbxNum1.Value * vbxNum2.Value
Case 3
vbxResult.Value = vbxNum1.Value / vbxNum2.Value
Case 4
vbxResult.Value = vbxNum1.Value ^ vbxNum2.Value
End Select
End
Now run the application, enter 10 and 2 for values and try all calculations.
Illustration 88: Calculating values 10 and 2
As you will notice the calculations run well, but now try with values 10 and 0. As soon as you
try dividing you will get an error as you are not allowed to divide by zero.
Illustration 89: Division by zero error
87
9. Your third application: NumPlay
As you will also notice you application is not reacting. To stop it click the Stop button in the
IDE toolbar (located below the menu bar).
9.3.2 Implement error handling
This is a good time to introduce some error handling. What you would like to know is the error
code. This is a number that can be used to indicate what went wrong.
Add some code to the btnCalc click event:
Public Sub btnCalc_Click()
Select iSwitch
Case 0
vbxResult.Value = vbxNum1.Value + vbxNum2.Value
Case 1
vbxResult.Value = vbxNum1.Value – vbxNum2.Value
Case 2
vbxResult.Value = vbxNum1.Value * vbxNum2.Value
Case 3
vbxResult.Value = vbxNum1.Value / vbxNum2.Value
Case 4
vbxResult.Value = vbxNum1.Value ^ vbxNum2.Value
End Select
Catch
Print Error.Code
Error.Clear
End
The keyword Catch will execute whenever an error in btnCalc_Click occurs. Error.Code will
return the error number. Error.Clear will clear the error so the application doesn't hang.
Catch
This instruction indicates the beginning of the error management part of a function or a
procedure.
The catch part is executed when an error is raised between the beginning of the function
execution and its end. This error can be raised by the function itself, or by any other function
called during its execution, provided that this deeper function has no catch part itself: the
deeper the catch part is, the more priority it has.
More on Catch see http://gambasdoc.org/help/lang/catch?v3
More on Error management see http://gambasdoc.org/help/cat/error?v3
Error
Use this class for managing errors raised while the interpreter is running.
Do not mix up with ERROR (with Capital letters)!!
More on Error see http://gambasdoc.org/help/comp/gb/error?v3
More on Error management see http://gambasdoc.org/help/cat/error?v3
Run the application and enter 10 and 0 and do a division. The console will output 26
88
9. Your third application: NumPlay
Illustration 90: Error 26 returned
Now that you know that error 26 occurs when trying to divide by zero you can Catch the error
and code it to do what you would like to happen.
In this case you would like to notify the user that it is not allowed to divide by zero and maybe
even set the focus to the second value.
Adapt the code for Catch accordingly
Public Sub btnCalc_Click()
Select iSwitch
Case 0
vbxResult.Value = vbxNum1.Value + vbxNum2.Value
Case 1
vbxResult.Value = vbxNum1.Value – vbxNum2.Value
Case 2
….
End Select
Catch
Select Error.Code
Case 26
Message.Warning(“You are not allowed to divide by zero!!”)
vbxNum2.SetFocus
Case Else
Print Error.Code
End Select
Error.Clear
End
Error.Code holds Integer values. And since this might be the first in more possible errors a
Select Case is used instead of an If Then for possible further errors to occur. For now if an
other error than 26 occurs you will see its number in the Console of the IDE.
Now run the application again and see what happens when you try to divide by zero.
89
9. Your third application: NumPlay
Illustration 91: Division by zero now handled properly
As you can see the application no longer allows division by zero and informs the user. All happens without hanging the application.
9.4 Working with numbers in text variables and text controls
Next you will have a look if numbers entered in a text control or held by a text variable (String)
can be used for calculations.
Place following controls on FrmMain with some properties pre-set:
1 TextBox Name → tbxNum1
1 TextBox: Name → tbxNum2
1 TextBox: Name → tbxResult
1 Button: Name → btnCalcText; Text → Calc text
1 TextBox: Name → tbxOneLine
When finished with placing all controls and setting all properties accordingly you should have
something like in the following illustrations.
Illustration 92: FrmMain after adding some controls
90
9. Your third application: NumPlay
9.4.1 Simple beginnings
As the title says, you are going to begin simple. Simple in this case means you right clicl on
button 'Call Text' and in pop p menu select Event → Click.
This will bring you to the code editor ready to code the click event of btnCalcText.
Now copy all the code in between Public Sub btnCalc_Click() and End () (so the code of
the entire routine except Public Sub … and End()) and paste it into the Public Sub btnCalcText_Click() event.
Next change all vbx... control names to tbx.. control names and the .Value to .Text. The result
should look like below
Public Sub btnCalcText_Click()
Select iSwitch
Case 0
tbxResult.Text = tbxNum1.Text + tbxNum2.Text
Case 1
tbxResult.Text = tbxNum1.Text – tbxNum2.Text
Case 2
tbxResult.Text = tbxNum1.Text * tbxNum2.Text
Case 3
tbxResult.Text = tbxNum1.Text / tbxNum2.Text
Case 4
tbxResult.Text = tbxNum1.Text ^ tbxNum2.Text
End Select
Catch
Select Error.Code
Case 26
Message.Warning(“You are not allowed to divide by zero!!”)
tbxNum2.SetFocus
Case Else
Print Error.Code
End Select
Error.Clear
End
Now hit <F5> to run the application and see what will happen if you simply start calculating
with text.
When started enter 1 in the two ValueBoxes and 1 in the two TextBoxes. Next click both buttons to see what happens.
Illustration 93: Calculating the text seems to work
91
9. Your third application: NumPlay
You will notice that calculating the text values seem to work out of the box.
9.4.2 Next challenge
Let's try something more challenging. Let's say you want to type '2 + 3' into txbOneLine, next
click btnCalcText and see the result in tbxResult. Something quite different.
For this you will need to get the two numbers and the operator out of a string. You can use
string functions to get this done.
Next you will need to transform the string numbers to numbers and determine what operator
to use on the two numbers. Last step is to return the result to tbxResult.
So back to the code editor in IDE to change the code to:
Public Sub btnCalcText_Click()
Dim sOperator, sHelp As String
Dim iB As Integer
Dim iNum1, iNum2 As Float
'-- find the first number –
iB = 1
iB = InStr(tbxOneLine.Text, " ", iB)
sHelp = Mid(tbxOneLine.Text, 1, iB – 1)
iNum1 = Val(sHelp)
'-- find the operator –
INC iB
sOperator = Mid(tbxOneLine.Text, iB, 1)
'-- find the next number –
iB = InStr(tbxOneLine.Text, " ", iB)
sHelp = Mid(tbxOneLine.Text, iB + 1, Len(tbxOneLine.Text) – iB)
iNum2 = Val(sHelp)
Select sOperator
Case "+"
tbxResult.Text = iNum1 + iNum2
Case "-"
tbxResult.Text = iNum1 – iNum2
Case "*"
tbxResult.Text = iNum1 * iNum2
Case "/"
tbxResult.Text = iNum1 / iNum2
Case "^"
tbxResult.Text = iNum1 ^ iNum2
Case Else
'– show a warning if an illegal operator is provided -Message.Warning("Unknown operator: " & sOperator)
End Select
Catch
Select Error.Code
Case 26
Message.Warning(“You are not allowed to divide by zero!!”)
tbxNum2.SetFocus
Case Else
Print Error.Code
92
9. Your third application: NumPlay
End Select
Error.Clear
End
As you can see three new functions are introduced. Mid(), a string function, INC is an arithmetical function and Val() a Localization and Translation function.
As you have already worked with several string functions, and have been shown where to find
them, it is part of your learning process to get acquainted with the online Gambas documentation and learn to comprehend the function Mid(). Val() and INC are explained below.
Expression = Val(String)
Val converts a string into a boolean, a number or a date, according to the string contents.
Expression is the variable that will hold the converted value
String is the string to convert.
The order Val checks to determine where to convert to is:
- Date/Time → returns Date & Time
- Floating point number → returns a floating point number
- 64 bit Long Number → returns a long number
- Integer → returns an integer
- Boolean → returns matching boolean value (0 or -1)
- Otherwise → returns Null
Val is a Localization and Translation Function. These functions are useful when dealing with
translations (language) and localisation (currency settings and such).
More on Val see: http://gambasdoc.org/help/lang/val?v3
Overview of Localization and Translation Functions see:
http://gambasdoc.org/help/cat/localize?v3
INC
Increments a variable.
Variable can be any target or assignment, but MUST be numeric
Same as:
Variable = Variable + 1
or
Variable += 1
INC is a Arithmetical Function. These functions are useful when dealing with numeric data.
Note: The opposite of INC is DEC (decrements a variable).
More on INC see: http://gambasdoc.org/help/lang/inc?v3
Overview of Arithmetical Functions see: http://gambasdoc.org/help/cat/arith?v3
Time to run your application once more and see some results.
Type these strings into tbxOneLine and click CalcText after each entry:
2+4
45 / 0
3 ) 56
a–3
93
9. Your third application: NumPlay
You will notice that most of above either returns a result or gives you a message what is
wrong, except for the last one. It does nothing.
Illustration 94: Division by zero taken care off
Illustration 95: Unknown operator taken care off
Of course it is possible to take care of this as well. Have a go at it yourself and see what you
can come up with.
The solution is provided on the next page, but really try figure out something yourself first before moving to the next page.
Remember, most learning takes place when things go wrong, not when everything works from
the beginning. It's the trying to make it work process that will stick much longer and build comprehension on the matter, not the copy/paste and run process.
Also know that of you come up with another solution to make it work doesn't make it wrong as
it works and you will have learned about Gambas doing so.
A little hint for on the road: Check out IsNumber() in the Gambas documentation.
94
9. Your third application: NumPlay
Public Sub btnCalcText_Click()
...
sHelp = Mid(tbxOneLine.Text, 1, iB – 1)
If IsNumber(sHelp) Then
iNum1 = Val(sHelp)
Else
Message.Error(sHelp & " is no number")
Stop Event
Endif
'-- find the operator –
iB += 1
...
sHelp = Mid(tbxOneLine.Text, iB + 1, Len(tbxOneLine.Text) – iB)
If IsNumber(sHelp) Then
iNum2 = Val(sHelp)
Else
Message.Error(sHelp & " is no number")
Stop Event
Endif
Select sOperator
...
End
As you might noticed, instead of using a Switch to escape the event from running excessive
code I chose to use the Stop Event. It does exactly what is says, it stops the event from running any further.
STOP EVENT
This statement must be used in an event handler. It tells the interpreter that the event that
called the event handler must be cancelled.
More on STOP EVENT see: http://gambasdoc.org/help/lang/stopevent?v3
Overview of Event management: http://gambasdoc.org/help/cat/event?v3
9.5 How about date and time
Next to numbers you will probably need to handle date and time information in some of the
applications you plan to built.
Let's have a look at that.
Place following controls on FrmMain with some properties pre-set:
1 DateBox Name → dbxDate
1 TextBox: Name → tbxDate1
1 TextBox: Name → tbxDate2
1 ValueBox: Name → vbxDate
When finished with placing all controls and setting all properties accordingly you should have
something like in the following illustrations.
95
9. Your third application: NumPlay
Illustration 96: Some extra controls added to play with date and time
9.5.1 Adding some code
First thing you are going to do is make sure that when selecting a date, the value representing the date is shown in vbxDate, the date part is shown in tbxDate1 and the time part is
shown in tbxDate2.
Select the DateBox and right click. In menu select Event → Change. Next type following
code:
Public Sub dbxDate_Change()
Dim iDays As Days
If Not IsNull(dbxDate.Value) Then
iDays = dbxDate.Value
vbxDate.Value = iDays
tbxDate1.Text = Format(dbxDate.Value, "dd-mm-yyyy")
tbxDate2.Text = Format(dbxDate.Value, "hh:nn:ss")
Endif
End
First thing you might notice is that dbxDate.Value returns a number of days if put into an Integer. Second thing you might notice is the Format() function.
With format you can convert values to strings in a certain output format.
So the “dd-mm-yyyy” makes sure the value is only the date part and in this order '19-092013'. If you would change it to “yyyy-mm-dd” it would look like '2013-09-19'.
Same goes for “hh:nn:ss” representing two digits for hours, minutes and seconds separated
by ':'
Make sure to have a look at the user defined formats in the Gambas documentation. There
are a lot of examples to be found. Link is in the box on the next page.
96
9. Your third application: NumPlay
String = Format(Expression, [, Format ])
Converts the expression into a string by using the format that depends on the type of
expression
Expression is the variable that will hold the value that will be converted
Format is the format description (how it needs to be returned)
The function can format date, times, numbers and currency.
Format is a Localization and Translation Function. These functions are useful when dealing
with translations (language) and localisation (currency settings and such).
More on Format see: http://gambasdoc.org/help/lang/format?v3
More on user defined formats see: http://gambasdoc.org/help/cat/userformat?v3
Overview of Localization and Translation Functions see:
http://gambasdoc.org/help/cat/localize?v3
Run the application and see what it returns when selecting a date. Next try the selecting the
next day and see the value below the DateBox go up with 1.
Illustration 97: After Date is selected the other controls are updated
accordingly
9.5.2 More date and time
To learn some more about date and time you will need to add one more control to your form.
This control is a special control named Timer.
You place it on your form but it will not be seen during runtime. Check the illustration on the
next page to see where it is located.
Place following control on FrmMain with some properties pre-set:
1 Timer Name → tmrInterval; Enabled → True
The Timer is a virtual object that gets triggered in a certain interval and runs the code you
would like. The interval is determined by setting the Timer property Delay (in milliseconds).
The timer can be placed anywhere on the form itself.
97
9. Your third application: NumPlay
Illustration 98: Timer object can be found in the toolbox on tab
'Special'
Illustration 99: Timer object can be anywhere on the form
Now this is what you are about to do. Every 1000 milliseconds (1 second), tbxDate1 will show
current date/time in format “ddd mmm yyyy hh:nn:ss”, tbxDate2 will show current date/time in
format “hh:nn:ss:uu”.
To get current date/time you will use the function Now.
Timer
This class implements a timer object
A timer object raises events regularly, each time it is triggered. The amount of time between
each event is specified by the Delay property.
More on Timer see: http://gambasdoc.org/help/comp/gb/timer?v3
Right click the Timer object and click on its Timer event and add following code:
98
9. Your third application: NumPlay
Public Sub tmrInterval_Timer()
tbxDate1.Text = Format(Now, "ddd mmm yyyy hh:nn:ss")
tbxDate2.Text = Format(Now, "hh:nn:ss:uu")
End
Now
Returns current date and time.
Now is a Date and Time Function.
More on Now see: http://gambasdoc.org/help/lang/now?v3
Overview of Date and Time Functions see: http://gambasdoc.org/help/cat/time?v3
Time to run your application and see what happens. Just sit back and watch the tbxDate1 and
2 change. If nothing happens you forgot to set the Timer property Enabled to true.
Illustration 100: Every second the tbxDate1 and 2 change their content
9.6 Another approach, enumerate
It was brought to my attention by Alain, one or our contributors, that NumPlay provided an excelent occasion to explain enumerating. So, thanks to Alain, here is a little extra added to the
chapter.
9.6.1 iSwitch enumerated
Earlier on (in 9.3.1) you used the Integer variable iSwitch and based on its value determined
what operator to use.
This is how the switch value represented the Operator in 9.3.1:
Operator:
+
*
/
^
Switch value:
0
1
2
3
4
99
9. Your third application: NumPlay
In the demonstrated code in 9.3.1, you as a developer need to know what value represents
what operator.
To make life easier you could implement enumeration. Enumeration can be used to declare a
list of integer constants. This will help you give a meaningful name to the different operator
values that need testing, as they are integers.
Using ENUM your code will look like this:
Private iSwitch As Integer
'– line below is added -Private ENUM PlusSign=0, MinusSign=1, MultiplySign=2, DivideSign=3, PowerSign=4
Public Sub Form_Open()
Me.Center
rbtAdd_Click
'To ensure lblOperator shows +
End
Public Sub rbtAdd_Click()
lblOperator.Text = rbtAdd.Text
iSwitch = PlusSign
'← changed
End
Public Sub rbtSubtract_Click()
lblOperator.Text = rbtSubtract.Text
iSwitch = MinusSign
'← changed
End
Public Sub rbtMultiply_Click()
lblOperator.Text = rbtMultiply.Text
iSwitch = MultiplySign
'← changed
End
Public Sub rbtDivide_Click()
lblOperator.Text = rbtDivide.Text
iSwitch = DivideSign
'← changed
End
Public Sub rbtPower_Click()
lblOperator.Text = rbtPower.Text
iSwitch = PowerSign
'← changed
End
By using ENUM you can now test iSwicht in your code against something more meaningful
like PlusSign instead of 0 or DivideSign instead of 5.
It makes for more readable and easier maintained code in a later stage of development.
100
9. Your third application: NumPlay
Enumeration declaration
{Public | Private } ENUM Identifier [ = Value ] [, Identifier [ = Value ] ...]
This keyword declares an enumeration or a list of integer constants.
If the Value of a constant is not specidied, then it is the value of the previous constant plus one,
or zero for the first constant.
More on Enumeration declaration see: http://gambasdoc.org/help/lang/enumdecl?v3
More on ENUM see: http://gambasdoc.org/help/lang/enum?v3
In this chapter you have worked with Arithmetical, Date and time and localization and
translation functions.
You will have noticed in this and previous chapters that a lot is possible using functions.
You will come to learn that they can be useful in a lot of situations.
They are very powerful tools to use and some of them you will be using a lot, so get familiar
with them.
Now in Gambas IDE click menu File → Quit. This gets you ready for the next chapter.
101
10.
Your fourth application: ImagePlay
10 Your fourth application: ImagePlay
10.1 What will be done in this chapter
Main focus will be images. for that you will built a new application.
This will involve
➢ Opening Gambas IDE and make a new project
➢ Make a main form
➢ Place a number of controls on the form
➢ Write some code
➢ Run the application from Gambas IDE
You can learn about:
➢ Working with the Gambas IDE
➢ Working with images
➢ Working with project file paths
➢ User interaction (input from user, output from application)
10.2 Start a new project and design a form
Open Gambas3 IDE and start a new graphical application project named ImagePlay.
Rename form FMain to FrmMain. Do this by right clicking FMain in the Project Browser and
next click Rename.
Place following controls on FrmMain with some properties pre-set:
1 PictureBox: Name → pbxOne; Width → 128; Height → 128
1 PictureBox: Name → pbxTwo; Width → 128; Height → 128
1 Label: Name → lblDimOne ; Text → empty; Alignment → Center
1 Label: Name → lblDimTwo ; Text → empty; Alignment → Center
1 Button: Name → btnSwitch; Text → Switch Image
When finished with placing all controls and setting all properties accordingly you should have
something like in the next illustration.
Illustration 101: Controls placed on FrmMain
102
10.
Your fourth application: ImagePlay
10.3 Let me see some images
10.3.1 Making some images
Before getting started with coding, you will need some images. You will create some new
ones right in the Gambas IDE.
First, in the Project Browser, right click the folder Data and in the menu click New → Folder.
Name the folder Images
Illustration 102: Create a new folder 'Images' in the project Data folder
Next, right click the folder Images and in menu select New → Image... Name the Image MyImage, extension PNG, width and height 128 pixels.
Click the newly made image and make something, like colour the background, draw a circle.
Just play a bit with the Image editor to make some image.
Illustration 103: Made some modern art image
103
10.
Your fourth application: ImagePlay
Now first save the image. Use the Save Project button in the button bar below the menu. You
will know if a image is saved when the image is visible in the Project Browser before its
name. To understand compare Illustration on previous page (unsaved MyImage.png) and the
illustration below (saved MyImage.png and NextImage.png).
Next, in the Project Browser, right click MyImage.png ans select Copy. Now right click
folder Images and in menu select Paste.
Rename the image file by right clicking it and selecting Rename.. Name the image NextImage.png and
Illustration 104: Image copied, edited and saved. That makes two works of
art.
The only goal of this little exercise is to end up with two different images sized 128 x128
pixels.
If you are missing the panel with image preview, left of the image editor, look for > and click
on it to make the panel appear. The > will change to < (see illustration below).
Illustration 105: Make panel appear
You will find more of these panels that can be visible or not. So now you know what to look
for.
10.3.2 Make the images appear
Mission is to make the images you have just created visible. For this you will go the the properties of both images and set the Picture property.
For this first select pbxOne and in the Properties/Hierarchy panel look for Picture. Click the
… to open the 'Select a Picture' form. In the left pane click open the folder Image and select
MyImage.png in the right panel.
104
10.
Your fourth application: ImagePlay
Illustration 106: Opening the 'Select a picture' form
Next click OK and see the image in the Form Designer.
Illustration 107: Image 'MyImage.png' in PictureBox picOne
Now do the same for pbxTwo, but use NextImage.png
Illustration 108: Both images in their PictureBox
105
10.
Your fourth application: ImagePlay
Now right click the form and select Event → Open and add next code:
Public Sub Form_Open()
Me.Center
End
Time to run the application and have a look at what you just created.
Illustration 109: Running ImagePlay for the first time
Well the images should be there. But the button 'Switch Image' still needs some work. Goal is
to switch the images in the PictureBoxes when clicking button 'Switch Image'.
In the editor you used the PictureBox property Picture to add the image to the PictureBox. So
simply exchanging their properties should do the job. But for that you will need a temporary
storage for one of the two properties.
So you need to do something like:
1. Store picOne Picture property in the temporary storage
2. Store picTwo Picture property in picOne Picture property
3. Store the temporary storage in picTwo Picture property
For the temporary storage you need a variable of type Picture. This because the Picture property of a PictureBox holds content of type Picture.
Picture
This class represents a picture.
The picture contents are stored in the display server, not in the process memory like an Image.
More on Picture see: http://gambasdoc.org/help/comp/gb.qt4/picture?v3
Back to coding the click event of btnSwitch:
106
10.
Your fourth application: ImagePlay
Public Sub btnSwitch_Click()
Dim picTemp As Picture
picTemp = pbxOne.Picture
pbxOne.Picture = pbxTwo.Picture
pbxTwo.Picture = picTemp
End
Run the application and click 'Switch picture' to see if it works.
Illustration 110: Clicking the button switches the images between the
PictureBoxes
10.3.3 Code the labels
There are still two labels on the form that need some coding. The labels will be used to show
the dimensions of the loaded image in the PictureBoxes above.
For this you will need to read the Picture properties Width and Height.
Back to coding:
Public Sub Form_Open()
Me.Center
lblDimOne.Text = pbxOne.Picture.Width & " x " & pbxOne.Picture.Height & " pixels"
lblDimTwo.Text = pbxTwo.Picture.Width & " x " & pbxTwo.Picture.Height & " pixels"
End
Run the application to see the result.
107
10.
Your fourth application: ImagePlay
Illustration 111: Labels now showing the image dimensions
When switching the images nothing happens to the Labels, so time to make a new image. In
'Project Browser' right click Image folder to create SmallImage.png (64 x 64) and BigImage.png (256 x 256).
Illustration 112: Two more png images made in the editor
Now go to the FrmMain in IDE and change the properties of pbxOne and pbxTwo. Make sure
pbxOne has LittleImage.png in its Picture property and pbxTwo has BigImage.png in its Picture property. Once done run the application again and see what it looks like.
108
10.
Your fourth application: ImagePlay
Illustration 113: Running the application with the new images
When running the application you will see that the labels give the proper dimensions, but the
images aren't shown properly.
LittleImage.png is TopLeft in pbxOne, BigImage.png can only be seen partial, because of its
size being 256 x 256, where pbxTwo is 128 x 128. So that are some things that need attention.
Try clicking button 'Switch Image' and see what happens.
Illustration 114: Images switch but labels show wrong dimensions
As you can see, the images switch, but the labels don't. This makes sense as you coded the
Form_Open event, meaning that only on opening the form the Labels get their content. There
is no code on the btnSwitch_Click event doing the same.
So more work is needed.
First you need to make sure that an image is shown in its total in the PictureBoxes, no matter
what its size is.
109
10.
Your fourth application: ImagePlay
Second you need to make the Labels show the proper dimensions.
Let's get to work:
First set the properties of the both PictureBoxes to meet this:
Alignment → Center
Stretch → True
The property Stretch will make sure the image is adapted to meet the dimensions of the PictureBoxes, the Alignment will center the image in the PictureBoxes.
Next more code is needed to make the Labels show the proper dimensions.
Public Sub btnSwitch_Click()
Dim picTemp As Picture
picTemp = pbxOne.Picture
pbxOne.Picture = pbxTwo.Picture
pbxTwo.Picture = picTemp
lblDimOne.Text = pbxOne.Picture.Width & " x " & pbxOne.Picture.Height & " pixels"
lblDimTwo.Text = pbxTwo.Picture.Width & " x " & pbxTwo.Picture.Height & " pixels"
End
Now run the application again.
Illustration 115: All works as expected
You will find all working as expected, even when switching the images the labels show th
proper dimensions.
One thing you might have notices is that the code used for showing the label dimensions in
both Form_Open and btnSwitch_Click event are exactly the same. This means you can write
a routine with that code and call the routine from both events, rather than having same code
at two places.
Advantage is that if you need to change something to the code, it only needs to be changed
at one place.
As you only need this routine on FrmMain you will code for a Private routine.
Here is the full code for FrmMain:
110
10.
Your fourth application: ImagePlay
Public Sub Form_Open()
Me.Center
ShowDimensions
End
Public Sub btnSwitch_Click()
Dim picTemp As Picture
picTemp = pbxOne.Picture
pbxOne.Picture = pbxTwo.Picture
pbxTwo.Picture = picTemp
ShowDimensions
End
Private Sub ShowDimensions()
lblDimOne.Text = pbxOne.Picture.Width & " x " & pbxOne.Picture.Height & " pixels"
lblDimTwo.Text = pbxTwo.Picture.Width & " x " & pbxTwo.Picture.Height & " pixels"
End
10.4 Loading images using code
Last part of image handling you will have a look at is loading the images using code.
For this you will need to add some more controls to the form.
Place following controls on FrmMain with some properties pre-set:
1 Button: Name → btnOneMy; Text → Load My
1 Button: Name → btnOneSmall; Text → Load Small
1 Button: Name → btnTwoNext Text → Load Next
1 Button: Name → btnTwoBig; Text → Load Big
When finished with placing all controls and setting all properties accordingly you should have
something like in the next illustration.
Illustration 116: All new controls placed on FrmMain
111
10.
Your fourth application: ImagePlay
10.4.1 The mission
Now that controls are in place this is what needs to be done:
1. btnOneMy needs to load MyImage.png into pbxOne upon clicking
2. btnOneSmall needs to load SmallImage.png into pbxOne upon clicking
3. btnTwoNext needs to load NextImage.png into pbxTwo
4. btnTwoBig needs to load BigImage.png into pbxTwo
To load an image into a PictureBox property Picture you will use Picture.Load.
Picture.Load
Static Function Load (Path As String) As Picture
Loads a picture from the disk.
More on Picture see: http://gambasdoc.org/help/comp/gb.qt4/picture/load?v3
To be able to load the picture you will need a path. Since the images are within the project
folder some more explanation is needed.
Illustration 117: Project
folder structure
For Gambas the Data folder presents the root folder. So addressing the Images folder will
give path: “Images”. If you need BigImage.png the path looks like: “Images/BigImage.png”16
When typing the code in IDE you will see that the auto-complete function will recognise the
path and files in there. Just hit Enter when proper file is selected instead of typing al.
Illustration 118: Auto-complete function of IDE will recognise the path
16
More on paths and Gambas: http://gambasdoc.org/help/cat/path
112
10.
Your fourth application: ImagePlay
The code looks like this:
Public Sub btnOneMy_Click()
pbxOne.Picture = Picture.Load("Images/MyImage.png")
End
Public Sub btnOneSmall_Click()
pbxOne.Picture = Picture.Load("Images/SmallImage.png")
End
Public Sub btnTwoNext_Click()
pbxTwo.Picture = Picture.Load("Images/NextImage.png")
End
Public Sub btnTwoBig_Click()
pbxTwo.Picture = Picture.Load("Images/BigImage.png")
End
After this all it takes is run and test.
Illustration 119: The pictures seem to load but the labels aren't adapted
10.4.2 Make the labels work again
Because you made a routine for updating the labels content, it shouldn't be to hard to get the
labels to work as needed.
Simply call the routine from each button click event should do the trick.
This is what is looks like:
113
10.
Your fourth application: ImagePlay
Public Sub btnOneMy_Click()
pbxOne.Picture = Picture.Load("Images/MyImage.png")
ShowDimensions
End
Public Sub btnOneSmall_Click()
pbxOne.Picture = Picture.Load("Images/SmallImage.png")
ShowDimensions
End
Public Sub btnTwoNext_Click()
pbxTwo.Picture = Picture.Load("Images/NextImage.png")
ShowDimensions
End
Public Sub btnTwoBig_Click()
pbxTwo.Picture = Picture.Load("Images/BigImage.png")
ShowDimensions
End
Again, run the application to see if the adaptation to the code works.
Illustration 120: Loading images now adapts the Labels accordingly
This concludes this chapter. In Gambas IDE click menu File → Quit. This gets you ready for
the next chapter.
114
11.
Your fifth application: SimpleTextEditor
11 Your fifth application: SimpleTextEditor
11.1 What will be done in this chapter
Main focus will be loading and saving data and menus. for that you will built a new application.
This will involve
➢ Opening Gambas IDE and make a new project
➢ Make a main form
➢ Place a number of controls on the form
➢ Make a menu and a toolbar
➢ Write some code
➢ Run the application from Gambas IDE
You can learn about:
➢ Working with the Gambas IDE
➢ Saving data to file
➢ Opening a saved file
➢ Making menus and coding them
➢ Making Toolbars and coding them
➢ Working with local file paths
➢ User interaction (input from user, output from application)
11.2 Start a new project and design a form
Open Gambas3 IDE and start a new graphical application project named SimpleTextEditor.
Rename form FMain to FrmMain. Do this by right clicking FMain in the Project Browser and
next click Rename.
Place following control on FrmMain with some properties pre-set:
1 TextArea: Name → txaMain; Text → empty
When finished with placing the control and setting all properties accordingly you should have
something like in the next illustration.
Illustration 121: FrmMain after placing the control
115
11.
Your fifth application: SimpleTextEditor
11.3 Making a menu
Believe it or not, in this chapter you are going to build a full functional text editor.
With the form made you already can enter text in the TextArea. Only thing missing is saving it
to a text file. For that you could add a save button, but that is not what you will be doing here.
To make a menu right click FrmMain in the IDE and select Menu editor... or press Ctrl + E.
Illustration 122: Select Menu editor...
Once the menu editor is opened add 9 menu entries by clicking button Insert 9 times.
Illustration 123: Adding 9 menu entries in the Menu editor
116
11.
Your fifth application: SimpleTextEditor
Assuming Menu9 is the first and Menu1 the last in the list, this is what you need to do for
each of the menu entries17:
Menu9: Name → mnuFile; Caption → File
Menu8: Name → mnuFileNew; Caption → New; Click button Indent in Toolbar (see below)
Menu7: Name → mnuFileOpen; Caption → Open..; Click button Indent in Toolbar
Menu6: Name → Seperator1; Caption → empty; Click button Indent in Toolbar
Menu5: Name → mnuFileSave; Caption → Save; Click button Indent in Toolbar
Menu4: Name → mnuFileSaveAs; Caption → Save As...; Click button Indent in Toolbar
Menu3: Name → mnuFileClose; Caption → Close; Click button Indent in Toolbar
Menu2: Name → Seperator2; Caption → empty; Click button Indent in Toolbar
Menu1: Name → mnuFileQuit; Caption → Quit; Click button Indent in Toolbar
Illustration 124: Indent the menu entry
Illustration below is how the end result should look like in the Menu Editor.
Illustration 125: The end result of editing the menu entries
Next close the Menu Editor and in IDE have a look at your form. Click on File to see what
happens.
17
You do this by clicking the menu entry in the menu editor list and next changing the properties in the fields below the menu list. The selected menu entry will be the one you are
editing.
117
11.
Your fifth application: SimpleTextEditor
Illustration 126: There is a menu File on FrmMain in IDE
11.3.1 Coding the menu entry New
Now click on New in the newly made File menu and you will be taken to the code editor to the
click event of this menu entry.
Lets add some code to FrmMain:
Public Sub Form_Open()
Me.Center
txaMain.Visible = False
End
Public Sub mnuFileNew_Click()
txaMain.Clear
txaMain.Visible = True
'Needed if another text document is already loaded
End
Now run the application and click menu File → New to see what will happen.
Illustration 127: Before and after clicking menu File -> New
118
11.
Your fifth application: SimpleTextEditor
11.3.2 Adding Icon and keyboard shortcut to menu entry New
Back to the Menu Editor to add an icon and a keyboard shortcut.
Once in Menu Editor click on the menu entry for New and set shortcut to CTRL and N
Illustration 128: Set the keyboard shortcut for menu New
Next at the property Picture click on the first button behind the textbox of Picture to open the
Picture dialog. Select Tab Stock and select the New icon18.
Illustration 129: Selecting the new icon
18
Icons might differ from desktop to desktop, depending on type of desktop and themes selected.
119
11.
Your fifth application: SimpleTextEditor
Click OK to close the Picture dialog after you selected the icon New. Next click OK again to
close the Menu Editor. Now run the application again and once running on your keyboard
press Ctrl + N and see what happens.
This should give you an new empty text area, same as when clicking the File → New entry.
So no extra coding to get the job done.
Now click on menu File to see your menu icon.
Illustration 130: File menu with the newly added icon
for New
Now that you can create a new text file and are able to enter text into the TextArea, next step
will be to save the content of the TextArea to a file.
11.4 Saving your first text file
When you want to save a newly made text file you will want to browse for a location, but when
the file has been opened for editing you will already know where to save.
So, what we actually have when saving a file is two situations:
1. New text file → no known location19
2. Existing text file → known location (as it has been opened from somewhere)
If you compare this to Save As you will have only one situation:
1. Existing text file → unknown location (although it has been opened from somewhere)
Seems that one thing you need to know is whether a text file is new or has been opened.
And it also seems that the actions required for saving a new text file are the same as doing a
save as for an existing text file.
Another thing of importance is, that when saving an existing file you will need to know its location (being path and full name).
These are the factors that will determine our approach in saving text files.
11.4.1 On a mission
Yes, I'm going to send you on a mission. A mission to:
19
Location in the meaning of path and file name.
120
11.
Your fifth application: SimpleTextEditor
1. Add a save icon to menu save
2. Add the keyboard entry Ctrl + S to the save menu
3. Have the code editor ready for coding the click event for the Save menu
Your menu should look like the illustration on the next page. If you don't know how, read the
back the part on how you did this for the menu entry New.
Illustration 131: Make sure your menu entry for Save has an icon and
keyboard entry
Menus and keyboard shortcuts
If you take a closer look at menus in common applications like web browsers, document
managers, mail clients or whatever, you will notice that menus have a certain order and that
this is actually of importance.
Why could this be important? Imagine one developer of applications placing a File menu on a
different location, another one placing Save in menu entry Edit, another one thing that Quit is
better of in menu Misc. That would create a lot of confusion amongst people using the different
applications as they would have to search for a function in different places depending on the
application they are using.
So having some sort agreement on menus makes life easier for those using your applications.
No user will expect the File menu to be at another location than right at the beginning of the
menu. No user will look for Save in any other menu that File. So in all it makes sense.
Same for keyboard shortcuts. If you would use Ctrl + S to open a file, a lot of users would get
confused as they are used to Ctrl + S for saving.
There are some directives for both Gnome and KDE development. These directives are known
as Human interface guidelines or hig. Have a look at them if you plan on designing applications
with menus, so you can make menus that appeal to the already present 'menu 'intuition of the
people using them.
More on Human interface guidelines: https://en.wikipedia.org/wiki/Human_interface_guidelines
Gnome hig on menus: https://developer.gnome.org/hig-book/stable/menus.html.en
KDE hig on menus: http://techbase.kde.org/Projects/Usability/HIG/Menu_Bar
11.4.2 Lets save some text
Now that all is a place you can start working for a solution based on the earlier analysis
made.
121
11.
Your fifth application: SimpleTextEditor
If a file is opened you know two things:
1. its location
2. that it is NO new file
So you could work with a variable that is set to true when a file is loaded. When false this
means you have a new file and no location. When true you have an existing file and a location. Expect that this variable will be needed all over the FrmMain, so best make it a Private
variable.
You have learned about the difference between Private and Public.
Private meaning that it can only be used within the class (in our case FrmMain.Class),
Public meaning you can use it in other classes as well (remember the search and replace example in TextPlay(T)wo).
Variables versus Private variables versus Public variables
For 'regular' variables you use Dim to declare them. Their reach is the Function or Method they
are declared in. You can't use them outside the function or method where they where declared.
As shortly discussed in chapter 5. Some good practices, and seen in the examples so far, I
precede my variable names with a letter like s or I. This is to identify the type of variable.
For Private variables you use Private to declare them. Their reach is the entire class they are
declared in. You can use them in any function or method within the class they where declared.
You can't use them in other classes.
When using Private variables I use the same convention as for 'regular' variables but add a $
sign in front of the letter to make them stick out and know as Private variables.
For Public variables you use Public to declare them. Their reach is the entire class they are
declared in and all other classes in the project. You can use them in any function or method
within the project they where declared. You can use them in other classes.
For Public variables I don't use the same convention as for 'regular' variables. I give them a
meaningful name beginning with a capital letter and no indication of type.
Some examples:
Type
String
Integer, Long, Short, Byte
Float
Boolean
Object (handle)
Collection
Arrays
'Regular'
Private
Public
sMyName
$sMyName
MyName
iMyNum
$iMyNum
MyNum
fMyNum
$ fMyNum
MyNum
bIsLoaded
$bIsLoaded
IsLoaded
hFileToLoad
$hFileToLoad
FileToLoad
cMyColl
$cMyColl
MyColl
determined by type (e.g Array of strings → sNames)
This approach is one that has grown throughout years of application development in other
languages. It is almost the same as the naming convention used in the in Gambas written
components source code and in the official examples.
I have nick named my naming approach the 'gbwilly convention' :)
Up to some coding. Add the following to FrmMain.class:
Private $bLoaded As Boolean = False
Public Sub Form_Open()
...
122
11.
Your fifth application: SimpleTextEditor
…
End
Public Sub mnuFileSave_Click()
If $bLoaded Then
'Just save the file
Else
'This means you have a new file
Print "New file"
'Now you will need a path and a file name to save to
Endif
End
Now run and make a new text file and watch the IDE console output. It should print 'New file'
when you click menu File → Save.
Next challenge you face is that you need some form of interaction with the user to provide the
application with a save path and a name of the file, for you to use when saving the file.
11.4.3 Get name and path to save to
To interface with the user for getting a save path and file name you will be using Dialog.
Dialog.SaveFile (gb.form.dialog)
Static Function SaveFile() As Boolean
Calls the file standard dialog to get the name of a file to save.
Returns TRUE if the user clicked on the Cancel button, and FALSE if the user clicked on the
OK button.
More on Dialog.SaveFile see: http://gambasdoc.org/help/comp/gb.form.dialog/dialog/savefile?
v3
More on Dialog see: http://gambasdoc.org/help/comp/gb.form.dialog/dialog?v3
So Dialog is what you will use, back to the code editor in IDE.
Public Sub mnuFileSave_Click()
If $bLoaded Then
'Just save the file
Else
'This means you have a new file
Print "New file"
'Now you will need a path and a file name to save to
'--- START OF ADDED CODE ---Dialog.Title = Application.Title & (" - Save text file")
Dialog.Path = User.Home
If Dialog.SaveFile() Then Return
File.Save(Dialog.Path, txaMain.Text)
Message.Info("File " & File.Name(Dialog.Path) & " saved.")
'--- END OF ADDED CODE ----
123
11.
Your fifth application: SimpleTextEditor
Endif
End
File.Save (gb)
Static Sub Save(FileName As String, Data As String)
Save the contents of a string into a file.
File.Name (gb)
Static Function Name (Path As String)
Returns the name component of a file path (name component is filename and file extension).
More on File.Save see: http://gambasdoc.org/help/comp/gb/file/save?v3
More on File.Name see: http://gambasdoc.org/help/comp/gb/file/name?v3
More on File see: http://gambasdoc.org/help/comp/gb/file?v3
User.Home (gb)
Static Property Read Home As String
Returns the home directory of the current user.
More on User.Home see: http://gambasdoc.org/help/comp/gb/user/home
More on User see: http://gambasdoc.org/help/comp/gb/user
Run the application, start a new text file, type some text.
Illustration 132: Ready to save my first file
Next click File → Save. In the dialog form browse to a location you want to save the file, in
the Name filed type 'test.txt' and click button Save.
124
11.
Your fifth application: SimpleTextEditor
Illustration 133: Dialog Save text file
You will receive notification when saved.
Illustration 134: Notification that the file has been saved
125
11.
Your fifth application: SimpleTextEditor
Run the application again open a new file, type some text, click File → Save and in the dialog
click Cancel.
Now that the file is saved you have a excuse to code opening a file, to see if the file was
really saved.
11.5 Opening your first text file
Opening the text file is kind of reverse to saving a text file.
For opening the text file you will need the user to browse to the file and select it. Next load the
content of the text file into txaMain.
Make sure to keep track of the fact that the file was loaded ($bLoaded) and to keep track of
its location (path and file name). So you need another variable to store the location. Best go
Private again as you might need it in more than one method.
11.5.1 Code for opening
To interface with the user for getting a file you will be using Dialog again.
Dialog.OpenFile (gb.form.dialog)
Static Function OpenFile([Multi As Boolean]) As Boolean
Calls the file standard dialog to get the name of a file to open.
Returns TRUE if the user clicked on the Cancel button, and FALSE if the user clicked on the
OK button.
More on Dialog.OpenFile see: http://gambasdoc.org/help/comp/gb.form.dialog/dialog/openfile?
v3
More on Dialog see: http://gambasdoc.org/help/comp/gb.form.dialog/dialog?v3
So Dialog,OpenFile is what you will use, back to the Gambas IDE.
Private $bLoaded As Boolean = False
Private $sPathFileLoaded As String
…
Public Sub mnuFileOpen_Click()
Dialog.Title = Application.Title & (" - Open text file")
Dialog.Path = User.Home
If Dialog.OpenFile() Then Return
txaMain.Text = File.Load(Dialog.Path)
txaMain.Visible = True
'Make the TextArea visible once file loaded
$sPathFileLoaded = Dialog.Path
'Store the full path of the loaded file
$bLoaded = True
'Set to True indicating NO new file
End
File.Load (gb)
Static Function Load(FileName As String) As String
Loads a file and returns its contents as a string.
More on File.Load see: http://gambasdoc.org/help/comp/gb/file/load?v3
More on File see: http://gambasdoc.org/help/comp/gb/file?v3
Run the application and try to open the file 'test.txt', you made and see if it works.
126
11.
Your fifth application: SimpleTextEditor
Illustration 135: Dialog Open text file
You should see that it works just fine. But there is one thing you forgot. The saving part is
coded for a new text file, but not for an opened text file.
So first back to the mnuSave click event.
11.5.2 Make sure an opened file can be saved
You can go straight to the IDE as you have managed to gather all intelligence (like a detective) on the opened file, the job should be easy.
Public Sub mnuFileSave_Click()
If $bLoaded Then
'Just save the file
'--- START OF ADDED CODE ---File.Save($sPathFileLoaded, txaMain.Text)
Message.Info("File " & File.Name($sPathFileLoaded) & " saved.")
'--- END OF ADDED CODE ---Else
'This means you have a new file
127
11.
Your fifth application: SimpleTextEditor
Once added, run the application, open test.txt, add a line of text and save.
Illustration 136: Saved the changes to the text file
Close the application and start it again. Open test.txt and you should see a changed file.
11.6 Little intermezzo
Time to have a look at the menu and how it looks. The fact that you can save, even when no
text file opened is at least disturbing. Just try it, run the application, do NOT open a file or create a new one and click menu File → Save. The application will not crash, but save an empty
file. But it does look odd.
So the file menu should behave according to the file being opened or not. When no file there
are some menu items you would like to see disabled.
These are:
1. Save
2. Save as...
3. Close
You know that $bLoaded will tell you if an application is loaded, so every time this Boolean is
changed, these menus need to change.
For this you will create a Private method that sets the above mentioned menu items to enabled or disabled according to the value in $bLoaded20.
Back to editing the code in the IDE.
Private Sub Form_Open()
...
SetFileMenu
'Add to the end of the Form_Open event
End
20
You see that $bLoaded is being used all over the project. Now you know why it has been declared Private.
128
11.
Your fifth application: SimpleTextEditor
Public Sub mnuFileOpen_Click()
…
SetFileMenu
'Add to the end of the mnuFileOpen_Click event
End
Public Sub mnuFileQuit_Click()
Me.Close
'About time you can close the application
End
Private Sub SetFileMenu()
If $bLoaded Then
mnuFileSave.Enabled = True
mnuFileSaveAs.Enabled = True
mnuFileClose.Enabled = True
Else
mnuFileSave.Enabled = False
mnuFileSaveAs.Enabled = False
mnuFileClose.Enabled = False
Endif
End
Now run the application and see the menu without and with opened text file.
Illustration 137: Part of the File menu disabled as
should be
This will work just test, but there is one exception when is will not work as expected. See if
you can discover it.
129
11.
Your fifth application: SimpleTextEditor
Well, did you discover it? If not run the application again from scratch. Click on File → New
(or use Ctrl + N), type some text and try to save it.
Illustration 138: Oops.., no way to save a new text
file..
Did you find it hard to save the text file? Well, I didn't manage. Guess all you need is some
more code to solve this problem.
So, when a new file is created you would like to be able to:
1. Save the file
2. Close the file (even without saving)
When closing a file make sure that $bLoaded is set to False, $sPathFileLoaded and txaMain
are empty.
Another thing to take care of is that when a new file is saved make sure that $bLoaded is set
to True and $sPathFileLoaded holds the path of the newly saved file.
Back to the editor:
Public Sub mnuFileNew_Click()
…
SetFileMenuNew
'Add to the end of the mnuFileNew_Click event
End
Public Sub mnuFileSave_Click()
…
Else
…
$sPathFileLoaded = Dialog.Path
130
11.
Your fifth application: SimpleTextEditor
$bLoaded = True
Message.Info("File " & File.Name(Dialog.Path) & " saved.")
Endif
End
Public Sub mnuFileClose_Click()
txaMain.Clear
txaMain.Visible = False
$sPathFileLoaded = Null
$bLoaded = False
SetFileMenu
End
...
Private Sub SetFileMenuNew()
mnuFileSave.Enabled = True
mnuFileClose.Enabled = True
End
Run the application and all should be working correctly. Start a new text file and see f you can
save it. Save it and the Save as should appear as well. Next close it and the File menu should
adapt to the new situation and the TextArea should be gone.
Next start another new text file, now close it and again see the menu change accordingly.
One more thing, make sure that menu File → Open, File → Close and File → Quit all get an
icon and File → Quit gets a keyboard shortcut (Ctrl + Q).
Illustration 139: The end result of some polishing of
the File menu
131
11.
Your fifth application: SimpleTextEditor
11.7 Back on track for Save As
Now all that is left for coding in the File menu is Save As...
You have arranged that the Save As menu item will only be seen when an existing project is
opened or a new one has been saved.
11.7.1 Code Save As menu item
What needs to happen when Save As is launched is actually about the same as when a new
document gets saved. The user will get a dialog to determine path and new file name. You
need to save to this user determines path and file name.
The code is as follows:
Public Sub mnuFileSaveAs_Click()
Dialog.Title = Application.Title & (" - Save As text file")
Dialog.Path = User.Home
If Dialog.SaveFile() Then Return
File.Save(Dialog.Path, txaMain.Text)
$sPathFileLoaded = Dialog.Path
$bLoaded = True
Message.Info("File " & File.Name(Dialog.Path) & " saved.")
End
Now run the application, open a text file and save it with another name.
Illustration 140: Save As dialog
132
11.
Your fifth application: SimpleTextEditor
You will see that this works as expected.
Illustration 141: Notification that the file was saved using a new name
You might also have noticed that the code for Save As is, except for the dialog form caption,
exactly the same. So there is some more work to be done
11.7.2 Simplifying the code for saving
This common code makes for a perfect example for a routine that can be called for both situation, simplifying your code, lessening the mount of code and making for better maintainable
code as you only need to modify code at one place instead of two.
Here is what you the changed Save and Save As event will look like:
Public Sub mnuFileSave_Click()
If $bLoaded Then
'Just save the file
File.Save($sPathFileLoaded, txaMain.Text)
Message.Info("File " & File.Name($sPathFileLoaded) & " saved.")
Else
SaveDialog(“Save”)
Endif
End
Public Sub mnuFileSaveAs_Click()
SaveDialog(“Save As”)
End
You'll notice they are a lot shorter and pass an argument for the Dialog form caption. (being
'Save' and 'Save As').
This how the SaveDialog() routine looks lik (it is private because you only use it in the current
FrmMain.class):
133
11.
Your fifth application: SimpleTextEditor
Private Sub SaveDialog(DialogCaption As String)
Dialog.Title = Application.Title & (" - " & DialogCaption)
Dialog.Path = User.Home
If Dialog.SaveFile() Then Return
File.Save(Dialog.Path, txaMain.Text)
$sPathFileLoaded = Dialog.Path
$bLoaded = True
Message.Info("File " & File.Name(Dialog.Path) & " saved.")
End
DialogCaption is the variable used to pass the argument. So calling SaveDialog(“Save”) will
pass the string “Save” to variable DialogCaption and use its value wherever DialogCaption is
used in the routine.
Illustration 142: The auto-help will know your new routine
As you see, for a variable used as an argument in a method (or function) I use no prefix to the
variable name, but a name that describes what argument will be for. It's type I will know when
using the routine in code as the auto-help will tell me (see illustration above).
Run the application to see it all at work as it should.
You should have one working very simple TextEditor that you can actually use in real life situation. But there is still room for improvement.
11.8 Putting the dots on the i
There is of course always room for improvement. Improving an application can take place on
many front like its functionality, its user friendliness, its looks, its bugs fixed just to name a
few.
You are going to focus on one improvement in functionality. It is more a lack of functionality
that needs to be implemented and that is rather disturbing.
You might have noticed that, when editing a file and next closing it the application will NOT
warn you about the file being changed and offering you an option to save it.
Another thing that will come around the corner when implementing this functionality is the x
on the main form. Users can use this to close the window (and thus the application) circumventing all your code to catch the 'file is edited and thus question for saving' code upon closing.
134
11.
Your fifth application: SimpleTextEditor
Another thing is that our form is rather small and when opening a large text file and next dragging the form bigger the TextArea will remain small. Some work there as well.
And last but not least, wouldn't it be nice to have a toolbar with open, save and other buttons?
So a few more thing to do before the application suits the needs.
11.8.1 Offer to save when closed after editing text file
The first thing you need to do is determine whether a file is changed or not. For this another
private variable is introduced $bChanged (a Boolean).
The control you need to check for changes is txaMain, so that is where $bChanged needs to
be set to true. TxaMain has a Change event and that is the one you need to code.
Not very much code needed to do the job:
Private $bChanged As Boolean = False
Public Sub txaMain_Change()
$bChanged = True
End
Next thing to do is to take care that when closing the application our change condition is
checked and when changed a possibility to save is offered.. This needs to be done at both
menu item Close and Quit.
Public Sub mnuFileClose_Click()
If $bChanged Then
'offer option to save
Else
txaMain.Clear
'← will trigger a change event and set $bChanged to true
txaMain.Visible = False
$bLoaded = False
$bChanged = False
'← set to false (see comment above)
$sPathFileLoaded = Null
SetFileMenu
Endif
End
Public Sub mnuFileQuit_Click()
If $bChanged Then
'offer option to save
Else
Me.Close
Endif
End
Code for offering to save is not yet there but you might notice that it will probably be exactly
the same for both Close and Quit event.
Now when offering the user to save the file you need to give some options like 'Yes', 'No' and
'Cancel' and act accordingly.
135
11.
Your fifth application: SimpleTextEditor
Now on several occasions Message has been used in the example applications and one of its
variants Message.Info (in this example application). Well, there is more you can do with Message so time to have a closer look.
You will be using Message.Warning as that makes sense, you want to war users of unsaved
work.
Message
This class is used for displaying message boxes
All Message functions can have up to three buttons:
- The first button is always the default button
- The last button is always the cancel button
Message boxes are modal, meaning the program is paused until one button is clicked.
When a message box is closed the index of the clicked button is returned.
Message.Warning
Static Function Warning(Message As String [, Button1 As String, Button2 As String, Button 3 As
String) As Integer
Displays a warning message with up to three buttons.
The index of the button clicked by the user is returned
More on Message.Warning see: http://gambasdoc.org/help/comp/gb.qt4/message/warning?v3
More on Message see: http://gambasdoc.org/help/comp/gb.qt4/message?v3
As indicated above when showing the Message.Warning (with three buttons) the application
will pause until user has made his choise.
When clicking 'yes' you need to save before Close or Quit
When clicking 'No' you Close or Quit without saving
When clicking 'Cancel' the Close or Quit has to be aborted.
Lets try to code this in a new private function for this:
Private Function WarningIsCancelled() As Boolean
Dim iAnswer As Integer
iAnswer = Message.Question("File has been changed!\nDo you want to save the project?",
"Yes", "No", "Cancel")
Select iAnswer
Case 1
mnuFileSave_Click
'<-- Yes: Let the code at the FileSave menu handle the saving
Return False
Case 2
Return False
'<-- No: So no saving
Case Else
Return True
'<-- Cancel: So cancelled
End Select
End
Why a function?
Well a function can do all a method can do, but it can also return something. In this case it returns True if button Cancel was clicked in Message.Warning. That is why the function is de-
136
11.
Your fifth application: SimpleTextEditor
clared As Boolean. The value after the word 'Return' has to be a Boolean as this is the value
returned when the function is called.
Since you will call this function from Close and Quit event it would be nice to know if 'Cancel'
was clicked. So when calling WarningIsCancelled() it will return either True or False.
When True, the warning was cancelled so the Closing or Quitting needs to be cancelled as
well. Hence the name of the function WarningIsCancelled, a name that gives meaning to what
the function actually does.
Now lets have a look at the changed code for Close and Quit event:
Public Sub mnuFileClose_Click()
If $bChanged Then
If Not WarningIsCancelled() Then
txaMain.Clear
'← Message.Warning received a yes or no
txaMain.Visible = False
$bLoaded = False
$bChanged = False
$sPathFileLoaded = Null
SetFileMenu
Endif
Else
txaMain.Clear
txaMain.Visible = False
$bLoaded = False
$bChanged = False
$sPathFileLoaded = Null
SetFileMenu
Endif
End
Public Sub mnuFileQuit_Click()
If $bChanged Then
If Not WarningIsCancelled() Then
Me.Close
Endif
Else
Me.Close
Endif
End
Time to run the application to see the effect of all the code.
First open a file, edit it and click File → Close
You should get a warning telling you that your file has changed and offering you the option to
save it.
137
11.
Your fifth application: SimpleTextEditor
Illustration 143: Closing after editing gives a
warning and option to save
Now click Cancel to see what happens. You should go back to the file without closing.
Now click File → Close again and next click No. The application will close the file.
Now open the same file and see if the changes where saved. They shouldn't be as you
clicked 'No'.
Now make some changes and click File → Close again and select Yes. The file should close
and upon opening the changes should be in the newly opened file.
Try the same for File → Quit.
If all that is done, one question: Did you discover the bug in your application?...
11.8.2 Bug!! What bug?!
When you intend something to work a certain manner to provide certain functionality and it
doesn't do that job under all circumstances, then you can call that a bug.
Try opening a text file, do NOT change the file and click File → Close. What happens? Do
you get a warning that your file has been changed when it isn't?
Something does seem to trigger the Change event of txaMain. First lets add a Print statement
to the Change event so you can check in console when it is triggered.
Public Sub txaMain_Change()
$bChanged = True
Print “Changed”
End
Now run the application keep your eye on the console.
When launching the application nothing happens in the console.
When clicking File → Open nothing happens in the console.
When selecting a file and clicking OK → console shows 'Changed'
138
11.
Your fifth application: SimpleTextEditor
Illustration 144: Changed shown in Console means Change event is
triggered
This actually makes sense as when loading a file to txaMain means a change form the point
of view of txaMain.
Here is the piece of code run before Change event is triggered.
Public Sub mnuFileOpen_Click()
Dialog.Title = Application.Title & (" - Open text file")
Dialog.Path = User.Home
If Dialog.OpenFile() Then Return
txaMain.Text = File.Load(Dialog.Path) '← triggers the change event
After txaMain.Text = File.Load(Dialog.Path), instead of running the next line of code, the
change event for txaMain is triggered. So the Gambas Interpreter will first execute the txaMain_Change() event before returning to the line of code after loading the file.
That is where you need to take care of business as change is triggered upon opening and
$bChanged is set to true.
Adding following line should solve the problem.
Public Sub mnuFileOpen_Click()
Dialog.Title = Application.Title & (" - Open text file")
Dialog.Path = User.Home
If Dialog.OpenFile() Then Return
txaMain.Text = File.Load(Dialog.Path)
$bChanged = False
'← Add this line
Now try running the application again. Do NOT change anything to the file and click menu
File → Close.
It should work properly now. So one bug down, up to the next one.
Open a file, change a few things and next click on the x to close the window (and thus the application). Next open the application again and open the file.
Did the changes save? I bet you they didn't, so there you have a second bug.
To catch the closing of a form by the user using x is done in the Form_Close() event.
For this you will code the Form_Close event and next cut and past the code of the mnuFileQuit_Click event to the Form_Close event. Next call the Form_Close event from
mnuFileQuit_Click event.
139
11.
Your fifth application: SimpleTextEditor
Public Sub Form_Close()
f $bChanged Then
If Not WarningIsCancelled() Then
Me.Close
Endif
Else
Me.Close
Endif
End
Public Sub mnuFileQuit_Click()
Form_Close
End
Now run the application, open a file, change something and click x. You will get the warning.
Click Yes and file will save and application closes.
Open the same file and see if the changes saved. Now change again and click x. Select Cancel and you will see that the application, instead of cancelling will close.
To solve that problem you will need one more line of code:
Public Sub Form_Close()
f $bChanged Then
If Not WarningIsCancelled() Then
Me.Close
Else
'← add this
Stop Event
'← and this
Endif
Else
Me.Close
Endif
End
STOP EVENT
STOP EVENT
This statement must be in an event handler. It tells the interpreter that the event that called the
event handler must be cancelled.
More on STOP EVENT see: http://gambasdoc.org/help/lang/stopevent?v3
More on Event Management see: http://gambasdoc.org/help/cat/event?v3
Now run the application again, open and change a file, click x and next Cancel and the application should stay opened.
In short, second bug down.
140
11.
Your fifth application: SimpleTextEditor
11.8.3 Resizing the application window
Check if you have got a ReadMe file or some other text file with a good quantity of text and
open it using SimpleTextEditor.
You will notice that with a lot of text a bigger size window would be better. So go to the border
of the SimpleTextEditor window and drag it bigger.
Illustration 145: Dragging the window bigger doesn't change the
TextArea
You will notice the window will resize, but the TextArea will not.
To solve this problem go to the FrmMain properties in the Gambas IDE. Set the FrmMain
property Arragement to Horizontal
Illustration 146: Set the Arrangement property of FrmMain
Now run the application, open you big text file and drag the main window bigger.
141
11.
Your fifth application: SimpleTextEditor
Illustration 147: The TextArea now does resize with the window...
TextArea does resize when dragging the window bigger, but not how you would like it. You
should try setting property Arrangement to Vertical as well and give it a go.
The one you need to make it work properly is Fill. So make sure to end there.
Illustration 148: Arrangement set to Fill does the job
142
11.
Your fifth application: SimpleTextEditor
11.8.4 Adding a ToolBar
To add a ToolBar you will need to go back to the design of your form and make some room
below your menu and above your TextArea.
Next add a Hbox above the TextArea.
HBox: Name → hbxToolBar
Illustration 149: HBox is found on the Tab Container
Now select the Hbox and add a ToolButton:
ToolButton: Name → tbnNew; Width → 22; Height → 22; Picture→ select the New icon from
stock 22.
You result should look like the illustration below. Check the hierarchy to see if tbnNew is actually placed inside the hbxToolBar (very important).
Illustration 150: All new controls in place
Next double click tbnNew and code its Click event:
Public Sub tbnNew_Click()
mnuFileNew_Click
End
Run the application and see what happens when clicking New in the Toolbar. Drag the window bigger and see what happens there.
Although the New button does produce a new empty text file, the forms looks a bit weird.
143
11.
Your fifth application: SimpleTextEditor
Illustration 151: A strange looking form, but New button works..
Seems you need to fix the Arrangement of the FrmMain. Give it a go and try the different options.
Now that you probably figured out that none will work, set the FrmMain property Arrangement to Vertical. Next set the txaMain property Expand to True.
Illustration 152: Set txaMain property Expand to True
Now give it another run. You should be able to make a new text file, drag the window bigger
and all should look just fine.
Now add a few more ToolButtons to hbxToolBar.
ToolButton: Name → tbnOpen; Width → 22; Height → 22; Picture→ select the Open icon
from stock 22.
ToolButton: Name → tbnSave; Width → 22; Height → 22; Picture→ select the Save icon
144
11.
Your fifth application: SimpleTextEditor
from stock 22.
ToolButton: Name → tbnSaveAs; Width → 22; Height → 22; Picture→ select the SaveAs
icon from stock 22.
ToolButton: Name → tbnClose; Width → 22; Height → 22; Picture→ select the Close icon
from stock 22.
The result should look like illustration below. Make sure the buttons are inside the Hbox.
Illustration 153: Make sure all ToolButtons are inside the HBox
Next code all the new ToolButtons. Just let them run the click event of the according menu
item.
Public Sub tbnOpen_Click()
mnuFileOpen_Click
End
Public Sub tbnSave_Click()
mnuFileSave_Click
End
Public Sub tbnSaveAs_Click()
mnuFileSaveAs_Click
End
Public Sub tbnClose_Click()
mnuFileClose_Click
End
Next take care that only those ToolButtons are enabled that need to be enabled, just like you
did with the menus.
For that you will need to go to the two private routines SetFileMenu and SetFileMenuNew.
They will need to look like this:
145
11.
Your fifth application: SimpleTextEditor
Private Sub SetFileMenu()
If $bLoaded Then
mnuFileSave.Enabled = True
mnuFileSaveAs.Enabled = True
mnuFileClose.Enabled = True
tbnSave.Enabled = True
tbnSaveAs.Enabled = True
tbnClose.Enabled = True
Else
mnuFileSave.Enabled = False
mnuFileSaveAs.Enabled = False
mnuFileClose.Enabled = False
tbnSave.Enabled = False
tbnSaveAs.Enabled = False
tbnClose.Enabled = False
Endif
'← added
'← added
'← added
'← added
'← added
'← added
End
Private Sub SetFileMenuNew()
mnuFileSave.Enabled = True
mnuFileClose.Enabled = True
tbnSave.Enabled = True
tbnClose.Enabled = True
'← added
'← added
End
You will notice how easy it is to make all this work because of a well set up code. Only a few
things need to be done to make all work.
Time for testing the application. Run and try your new buttons, see if they are enabled at the
proper times, if they work.
Make a new file with the New button, type some text and save it with the Save button. Close it
with the Close button and reopen with the Open button. Does all work as expected?
Open a file and change it, try to close it with the button. Do you get a warning that file has
been changed?
All should work as expected and like the menus worked.
Illustration 154: A running resizeable SimpeTextEditor with Toolbar
146
11.
Your fifth application: SimpleTextEditor
All that is left doing is make the ToolBar look a bit better. Simply set the property Spacing of
the hbxToolBar to True
Illustration 155: Toolbar with property Spacing set to False
Illustration 156: Toolbar with property Spacing set to True
That wasn't to hard.
11.8.5 Reordering menu items
One more thing before this chapter comes to an end. In most applications you will find the
menu item Close just above Save. You have it below SaveAs. Lets make a change.
Open the Menu Editor. Select the menu item Close and click the Move Up button twice.
Illustration 157: A click on Move Up button brings the item higher
147
11.
Your fifth application: SimpleTextEditor
11.8.6 Adding new menus
You can also easily add a new menu. And that is your next mission. Add these menu items to
the bottom of the current ones
Menu4: Name → mnuView; Caption → View
Menu3: Name → mnuViewToolBar; Caption → Toolbar; Checked → True;Click button Indent
in Toolbar
Menu2: Name → mnuHelp; Caption → Help
Menu1: Name → mnuHelpAbout; Caption → About... Click button Indent in Toolbar
Illustration 158: Added menus with ToolBar menu item set checked
Run the application to see your new menus. Have a special look at menu View → Toolbar as
this one has a checkbox.
Illustration 159: A new menu View Toolbar
148
11.
Your fifth application: SimpleTextEditor
Now when the menu item Toolbar is checked you want the ToolBar to be visible. When unchecked it needs to be invisible.
For the About menu item in menu Help you will code a simple Message.
Public Sub mnuViewToolBar_Click()
If mnuViewToolBar.Checked Then
mnuViewToolBar.Checked = False
hbxToolBar.Visible = False
Else
mnuViewToolBar.Checked = True
hbxToolBar.Visible = True
Endif
End
Public Sub mnuHelpAbout_Click()
Message.Info(Application.Name & " " & Application.Version & "\nAn example application by
W. Raets\n\nGNU General Public License version 3")
End
For the mnuViewToolBar you check its checked status and change it. Clicked when the Toolbar item was checked will uncheck it and vice versa. Besides that it will make the ToolBar
hbxToolBar visible or invisible accordingly.
The mnuHelpAbout code is just a simple Message.Info.
Have a look at your result.
Illustration 160: With ToolBar checked
Open a text file and click menu View and see the Toolbar item checked. Now click the menuitem Toolbar and see the Toolbar disappear (see illustration on next page).
149
11.
Your fifth application: SimpleTextEditor
Illustration 161: With Toolbar unchecked
Click menu Help → About... to see your About screen.
Illustration 162: Menu Help -> About shows some info on the
application
11.8.7 Application caption
The last 'dot to put on the I' is the application caption. Default it shows the applications name,
but it could be used differenty.
When a text file is open it could show the application name and the name of the text file.
When a new text document is made it could show application name and 'new text document'.
As the caption has to be set according to the current state of the text loaded into txaMain, it is
going to be needed at more than one place in our FrmMain.class. A private routine would be
the proper road to take.
Basically there are two situation:
150
11.
Your fifth application: SimpleTextEditor
1. No document loaded → no file name
2. Document loaded → file name known or file name is 'new text document'
If you write a private method that sets the caption these file names need to get passed to the
private method. For that you use an argument, but since there is not always a file name to
pass you need to make the argument Optional, meaning you can provide the argument when
calling the method but you don't need to.
Back to the code editor in IDE to write the routine:
Private Sub SetAppCaption(Optional AppCaption As String)
If IsNull(AppCaption) Then
Me.Caption = Application.Name
Else
Me.Caption = Application.Name & “ - “ & AppCaption
Endif
End
Because AppCaption is an optional argument, meaning it can be empty, you need to check
what cause of action to take when empty (IsNull).
Next step is to check at what places the method SetAppCaption needs to be called.
First place is when a new document is made. The caption will need to show 'New text document' alongside the application name.
Public Sub mnuFileNew_Click()
txaMain.Clear
txaMain.Visible = True
SetAppCaption(“New text document”)
End
Now run the application and click button New in the Toolbar.
Illustration 163: 'New text document' added to
application caption
151
11.
Your fifth application: SimpleTextEditor
Second place to check is when opening a text file.
Public Sub mnuFileOpenClick()
...
txaMain.Text = File.Load(Dialog.Path)
'← this is where the file gets loaded
SetAppCaption(File.Name(Dialog.Path)) '← this is where you set the caption
...
End
Again run and open a text file and see the file name appear in the caption.
Illustration 164: Caption showing the name of the opened
text file
Third place to check is when a new document is saved (so it has a name) and when an existing document is saved as (so it will get another name).
This all happens in method SaveDialog. So that is where you need to add the code:
Public Sub SaveDialog()
...
File.Save(Dialog.Path, txaMain.Text)
'← this is where the file gets saved
SetAppCaption(File.Name(Dialog.Path)) '← this is where you set the caption
...
End
And last but not least, the caption should be set when opening the form:
Public Sub Form_Open()
Me.Center
SetAppCaption()
...
'← this is where you set the caption (no name known)
152
11.
Your fifth application: SimpleTextEditor
Run your application once more and try some different things, like starting a new text document and saving it, next save as. If you see the caption changing the application is finished
for now.
Illustration 165: Save the new text document
Illustration 166: After saving the caption changed
11.9 A last note on code organisation
Since no application is really free of maintenance, you should organise your code in such
manners that, in a later stage (this can be months and other applications later), you understand what you have been doing in the past.
Comment can contribute, as can ordering your code.
On the next illustration a screenshot of the code of this project in my IDE. You will see that I
placed all menu code together, all toolbar code together, all private routines together. All these
groups have a comment indicating where they start.
153
11.
Your fifth application: SimpleTextEditor
Illustration 167: FrmMain.class code organised in certain order
Not visible on the screenshot is that at certain point in the code I add comment to explain to
myself (in a later stage) what I did there. Might sound strange, but believe me, I am very
happy that I give myself these presents.
This concludes this chapter.
In the next chapter you're going to continue to work with SimpleTextEditor.
154
12.
End note for pre-release 1
12 End note for pre-release 1
This work is not finished yet. More chapters will be added as soon as possible and current
ones might be further revised.
Planned for the next chapter (actually this chapter 12) is printing.
After that you will be diving into some more complex situations when it comes to handling
data and saving it, you will learn some new more complex controls and have a closer look at
what is possible with form classes. This journey will take several chapters.
And what will be next I'm not sure about, a closer look at the IDE will be part of it fir sure. Expect at least 6 or 7 more chapters added to the final release. Maybe in between another prerelase will become available, a bit depending on how long things take to write.
Meanwhile I hope you enjoyed the first 11 chapters and working with Gambas. Make sure to
install the application GambasLearning (see Appendix VI) , for updated information on this
and other 'How To Gambas'-guides and more to help the beginning Gambas developer.
To be continued...
P.S. If you encounter any irregularities in this release please report them back (see Appendix V) and help improve the guide.
155
13 Appendices
Appendix I: Linux command reference
If you are new to Linux, here are some commands that could be useful when installing Gambas from the official website or from SVN.
File commands
ls
ls -al
cd dir
cd
cd /
mkdir dir
rm file
rm -r dir
rm -f file
rm -fr dir
lists the current directory
lists the current directory (hidden files included)
change the directory dir (example: cd /usr/bin)
change to home directory
change directory to root directory
make directory dir (example mkdir Gambas3)
removes file file (example rm myinfo.txt)
removes directory dir (example rm Gambas3)
forced remove file file (example rm -f myinfo.txt)
forced remove directory dir (example rm -rf Gambas3)
System information
df
du
uptime
uname -a
free
show disk usage
show directory usage
show system uptime
show kernel information
show memory and swap information
Installation from source
./configure
make
make install
Configure the package
Compile the package
Install the package
I
Appendix II: Subscribe to the official Gambas mailing lists/Forum
When you are experiencing problems installing Gambas and you don't manage to solve them
you can always report them on the Gambas mailing list.
For this you will first need to subscribe to the mailing list. Open a browser and go to the Gambas website and click on the menu 'Mailing lists/Forums'
Illustration 168: Gambas website - Menu Mailing lists/Forums
This will open an overview of the available mailing lists and a forum.
Illustration 169: Gambas website - Overview Mailing Lists & Forums
For reporting your problems use the 'Gambas Users' list.
The 'Gambas Developers” and 'Gambas Subversion Commits” lists are meant for those
working on the development of Gambas3 (or those just curious)
II
Then there is a Spanish and French user list and next the forum for those who dislike mailing
lists.
Option 1: Subscribe to Gambas Users mailing list
When clicking 'Gambas Users' you get to the page to register to the mailing list.
Illustration 170: Subscribe to the Gambas-user mailinglist
Once registered you will receive all posts on the mailing list in the inbox of the mail account
you signed up with. You will also be able to send mails to the list.
Option 2: Use the forum instead of the mailing list
If you dislike mailing list there is a second option. Click 'http://www.nabble.com/Gambasf3425.html' to go to the forum.
III
Illustration 171: Gambas mailing list Forum
On the forum you will find all the topics and posts from the mailing list. To post you will need
to register an account.
IV
Appendix III: Reporting problems on the official Gambas mailing list
When reporting your problems on the mailing list first consider a few good practices.
1. Search the official Gambas mailing list forum for an answer before asking questions
2. Provide details on your system when reporting your problem
3. Provide details on your problem when reporting your problem
4. Be clear on what goes wrong and where it goes wrong and the steps that took you there
5. Provide a source archive with a project that shows the problem
When having problems provide these details on your system:
1. Kernel information (use uname -a in a terminal)
2. Distribution name and version (Example: Linux Mint 13 Maya)
3. Desktop used (Examples are: Gnome, KDE, LXDE, xfce, Mate, Cinnamon,...)
4. Gambas version
All this can be found in the Gambas IDE menu ? → System informations...
Illustration 172: Gambas IDE - System information form
Just copy/paste into your mail or attach a text file you pasted the information into.
V
Appendix IV: White Island Software and GambasForum quick tour
On White Island Software and GambasForum a Project Collaboration Forum 'How to Gambas 3' has been created open to the public21. Here is a quick tour to get you started on the
forum.
To go to White Islands Software and GambasForum open a web browser and type
http://whiteislandsoftware.com/index.php?page=start as destination.
Illustration 173: White Island and GambasForum (circled the login and join)
Once there log in or join (see illustration above). When logged in you will be brought to the
same page again but now with more details where the login used to be.
Click on Forum in the top menu (just behind Home). You will get an overview of all forums
present when scrolling down.
Forums are categorized into these categories with following forums per category 22:
➢ Website Community
➢ Website Community
➢ Gambas News
➢ General
➢ Introduce yourself
➢ General chat
➢ Graphic and Images
➢ Website comment topics
➢ The GambasForum Coder
➢ Gambas IDE
➢ Ask Quin
➢ Gambas version 3
➢ Gambas versions 1 and 2
➢ Raspberry Pi
➢ Gambas based projects
➢ Member's Lounges
➢ gbWilly
21
22
You can visit it as guest and read all information. To post questions on the forum you need
to make a free account.
Categories and forums as present on October 14th 2012.
VI
sholzy
konaexpress
➢ NatashaDaystar
➢ Piga Software
➢ Gambas Project hosting
➢ Important notices (Read-only)
➢ The Admin's lounge
➢ How To.../Howdo I...
➢ Domains
➢
➢
If you want to look for something or post something make sure to go to the proper category
and forum.
When you visit the GambasForum to check what you missed since your last visit there is an
easy option at the top left of your user name 'Post since last visit'. Click it and you will see
what you missed out on.
Illustration 174: Search, Post since last visit and Topics with unread posts
Another handy option is the 'search' button for searching the forum if you have some problem
with Gambas. If no answer to your problem can be found just start a new topic in the proper
category and forum.
'Topics with unread posts' can come in practical at times as well.
With this information you have the basics to get started on the forum. There is a lot more out
there like a software repository, guides and so on, but that is not what this guide is about.
VII
Appendix V: Getting help with the 'How to Gambas 3' guides
On White Island Software and GambasForum a Gambas based project 'How to Gambas 3'
has been created open to the public23.
It is set up so that people having trouble with the guide can go there and ask their questions
(or check if someone else asked the same) or do suggestions on the manual.
These questions and suggestions will be taken into account on improving the guides. So feel
free do make good use of this possibility.
First browse to the White Island Software and Gambas Forum24 and login (if you want to post
your problem).
Click on 'Forum' in the topmenu and scroll down to the category 'Gambas based projects'
where you will find the forum 'How to Gambas 3' under gbWilly.
Illustration 175: Gambas based projects with sub forum 'How to Gambas 3'
If you click the forum you will find several sub forums and some general topics.
Current sub forums are:
➢
Installing Gambas
This contains topics concerning the guide 'Installing Gambas'.
Post your questions and/or suggestions on the guide 'Installing Gambas' here.
➢
Building GUI Applications
This contains topics concerning the guide 'Building GUI Applications'.
Post your questions and/or suggestions on the guide 'Building GUI
Applications' here
➢
Project member Section
This section is for project contributors only. If you want to contribute send
a PM on the forum to gbWilly.
The number of sub forums will grow with the number of guides is the series.
23
24
You can visit it as guest and read all information. To post questions on the forum you need
to make a free account.
Link to website: http://whiteislandsoftware.com/index.php?page=start
VIII
Illustration 176: Sub forums and topics of 'How to Gambas 3' forum
Each sub forum will have its own topics. Make sure to post in the proper sub forum. So for
questions on this manual 'Building GUI Applications' you click Building GUI Applications to
see the topics present.
Illustration 177: Topics in sub forum 'Building GUI Applications'
Three topics are of importance:
➢
Suggestions for improvements
➢
Problems with instructions in the manual
➢
Other questions
The topics are kind of self explaining, just post in the proper one and it will be picked up.
IX
Appendix VI: Application Gambas Learning – a learning aid for Gambas
Gambas Learning is an application to provide some aid to those learning Gambas.
Illustration 178: Gambas Learning - a learning aid for Gambas
The application provides you with:
➢ an overview and download of the 'How To Gambas 3' guides (most recent version)
➢ Gambas 3 code snippets for common tasks
➢ a direct access to the Gambas 3 language index
➢ a direct access to the Gambas 3 component index
➢ a direct access to the Gambas 3 error messages index
➢ a direct access to the How To Gambas forum
The application receives remote metadata updates25 on the number, version and state of
guides available. New code snippets that are available are also part of the metadata updates
of Gambas Learning and will update the code snippets seen in Gambas Learning.
For more screenshots and download visit:
http://howtogambas.org/
25
This requires a working internet connection
X
Appendix VII: Overview of the 'How To Gambas 3' guides
Here is the list of guides published and planned:
➢ 1. Installing Gambas
First version published: November 10th, 2012
➢ 2. Building GUI Applications
First 11 chapters pre-published: September 29th, 2013
XI
14 Bibliography
Primary sources
Gambas website: Gambas 3 Documentation, URL: http://gambasdoc.org/help/?v3 [Last accessed 28/09/2013].
Gambas website: Reporting a problem, bug or crash, URL: http://gambasdoc.org/help/doc/report?view [Last accessed
14/10/2012]
Secondary sources
Wikipedia: Gambas, URL: http://en.wikipedia.org/wiki/Gambas [Accessed 09/11/2012]
Wikipedia: C Datatypes, URL: https://en.wikipedia.org/wiki/C_data_types [Accessed 02/03/2013]
Wikipedia: Object-oriented programming URL: http://en.wikipedia.org/wiki/Object-oriented_programming [Accessed
23/09/2013]
XII