Introduction To Programming With Xojo
Introduction To Programming With Xojo
CONTENTS
1. Foreword
2. Acknowledgments
3. Conventions
So while this book does focus on Xojo, the concepts that are
introduced are applicable to many different programming
languages. Where possible, some commonalities and differences
are pointed out in notes.
ii
Acknowledgements
iii
see the ¬ symbol, don’t type it in; just keep typing what’s
Conventions indented on the next line. So if you see code like this:
Because Xojo can run on different operating systems and build theMessage = theMessage + myString ¬
apps for different operating systems, some of the screenshots in ! + EndOfLine
this book were taken on Windows and some were taken on OS
X . One of the sample apps is web-based, so you’ll see that its You should type it in all on one line, like this:
screenshots were taken in a web browser.
theMessage = theMessage + myString + EndOfLine
As you read this book, you also will notice different formats of
text. Another format you will see is steps. A step looks like this:
One format is code examples. Anything in a code example is 1) This is something you’re supposed to do. You might be
meant to be typed into Xojo exactly as it appears on the page. A asked to set “Some Text” as something’s caption. If that
code example looks like this: happens, type what’s inside the quotation marks, but not the
quotation marks themselves.
Dim x As Integer
This is a more detailed explanation of the step above. It will probably
Dim y As Integer
provide more details about the task you’re working on.
Dim z As Integer
x = 23
Most of the code examples in this book are accompanied by a
y = 45
z = y * x series of steps explaining how things work.
MsgBox Str(z)
Finally, you may see a note. A note looks like this:
iv
Copyright & License
This work is copyright © 2012-2016 by Xojo, Inc.
If you wish to print copies of this book, you are hereby granted
permission to do so, provided all of the content remains intact,
including this link to the freely available PDF: http://
www.xojo.com/learn/
v
Chapter 1
Hello, World!
CONTENTS
1. Chapter Overview
2. Getting Around
4. Hello, World!
5. Swatting Bugs
1.1 Chapter Overview
Welcome to Introduction to Programming with Xojo.
This chapter introduces the IDE. You will learn how to navigate
the IDE, how to customize it, how to organize your projects, and
how to run and build your own applications. Some of the
concepts introduced in this chapter may not make much sense at
the moment, but they will be explained in more detail in later
chapters.
7
1.2 Getting Around
Begin by opening the Xojo application. You will be prompted to
choose a template for a new project. Select “Desktop” and press
the OK button.
By default, you see a window with two distinct areas. The larger
area, known as the pasteboard, holds an empty window. This is
where you can begin to design the user interface for your
application. The left pane, known as the Navigator, holds a list of
items in your project. By default, you probably won’t see anything
As you can see from the screenshot, Xojo can build many there other than App, Window1, and MainMenuBar. Beneath the
different types of apps, including web-based apps, console (or Contents you should see some options for Build Settings. Build
command line) apps and iOS apps. Settings allow you to change the settings of the application you
will be creating, such as its name, version number, and icon.
After you choose a template, Xojo will create an empty project
based on that template. The project is the file that stores all of the Above the pasteboard at the top of the window is the toolbar. The
source code, user interface designs, and information about the two rightmost buttons will toggle the visibility of the Library and
app you are developing. The default empty desktop project looks the Inspector. The Library is a list of controls that you can add to
like this: your interface (simply by dragging and dropping), while the
Inspector allows you to modify the properties of whatever you
8
have selected in the pasteboard. For example, if you add a button
to your interface, you may select that button and use the
Inspector to change its caption or physical size. Take a few
moments now to browse the Library and Inspector.
This view is called the Layout View. In Layout View, you visually
design the look and feel of your application. Another important
view is Code View. This is where you will enter the Xojo source
code that controls the behavior and functionality of your app. The
easiest way to get started in Code View is to use the Insert Menu
to insert an Event Handler. Events will be discussed in much As you add components to your projects, you will see them in the
greater detail in a later chapter, but for now, you need to know Navigator, whether you are in Layout View or Code View. You may
that events allow your application to react to actions taken by double click on an item in this list to open it for editing. You may
your application’s end users as well as actions that the computer also drag and drop these items to arrange them in the order you
or operating system may cause while your application is running. desire. The order in which you arrange these items will have no
Select Event Handler from the Insert Menu and choose Open in bearing on the performance or functionality of your built
the list of events that appears. application; it is up to you to organize your project in a way that
makes sense to you. You may even add folders and subfolders if
Notice how the interface changes. The pasteboard disappears
you wish to organize your project in such a way. To add a folder,
and is replaced by the code editor, while the Navigator and
go to the Insert Menu and choose Folder. You can then drag and
Inspector or Library remain visible. The name of the event that
drop other project items into the folder.
you’re editing will be visible at the top of the code editor, as seen
in the screenshot below. The Insert Menu is one that you will be using often as you build
more and more complex applications. In addition to folders, you
will use it to add classes, windows, and other components to
your projects. Once again, these concepts will be explained in
later chapters.
9
from the Project menu.
1.3 Running and Building
Remember, you can run your projects with the free version of Xojo,
On the toolbar, one of the buttons that appears is the Run button. but you must purchase a Xojo license in order to Build your apps.
Clicking this button will tell Xojo to build a temporary copy of your
project and execute it. You may also run your project by choosing
If you build your project now, you will have an app that can be
Run from the Project menu. Although you have yet to add any
run, but it will have a few issues, such as a rather generic name
code to your project, go ahead and run it now.
and icon and the fact that it does not do much of interest at this
You will be presented with a blank window. While this may not point.
seem impressive, quite a lot has already been accomplished.
First, your project has been converted from a Xojo project file into
an app that can be run on your computer. In addition, your app
can respond to menu commands and keyboard shortcuts and
react accordingly. For example, if you press Command-Q on
Macintosh or Alt-F4 on Windows, your blank app will quit and you
will be returned to Xojo.
Running your app in this way allows you to access the Xojo
debugger, which will be covered later in this chapter. What it does
not give you, however, is an app that you can share with other
people. The app produced by running is temporary and is only
intended to be used for testing and debugging.
Some of these problems are simple to solve. In the Navigator,
To create an app that can be shared, you need to build your
locate the App item in the list and select it. This item, called a
application. The Build button is found directly to the right of the
class, allows you to set properties that will apply to your app as a
Run button on the toolbar, or you may choose Build Application
whole. With the App class selected, click on the Inspector button
in the toolbar.
10
The Inspector is grouped into several sets of properties. Not all of bugs. If you were to enter 3 for the MajorVersion, 1 for the
these sets will be covered at this time. Notice that there is a MinorVersion, and 4 for the BugVersion, your application would
separate group of build settings for each platform for which your report itself to the operating system as version 3.1.4.
project can be built: Windows, Linux, and OS X. Find the setting
Below BugVersion is StageCode, which offers four options:
appropriate for your platform and change the App Name property.
Development, Alpha, Beta, and Final. As you work on adding
code to your project, the StageCode should be set to
Development. Once your application is feature complete, you
should change the StageCode to Alpha. StageCode should be
set to Beta once your application is nearly complete and most of
your internal testing is complete. Before you release a build of
your application to the world at large, you should set the
StageCode to Final.
The other problem with your project at this point, though, is that it
does nothing of interest or value. This will be remedied in the next
section.
11
on Window1 to open it in the Layout Editor. This is the view that
1.4 Hello, World! you will use to design the user interface for your projects.
While computer programming is far from an ancient art, it does As noted above, there are three main areas that you will see in
have some traditions. One such tradition is the Hello World app. Layout View. The largest area, found in the center, is called the
Whenever a developer is learning a new language, it is traditional pasteboard. Within the pasteboard, you will see an empty
to start with a very simple app that simply announces its window. On the left side of the window is the Navigator, which
existence by declaring, “Hello, World!”. You will not be breaking contains the items in your project. On the right is either the
with said tradition, so this section will help you build your own Inspector or the Library. The Library contains interface elements
Hello World app. A screenshot of the final app is below. that you may add to your window (or position elsewhere on the
pasteboard).
1) Find the Default Button in the controls list and drag it onto
the window in the pasteboard.
First, turn your attention to the Library. As you scan up and down the list,
you will see various interface elements, some of which should look familiar,
such as the Check Box, various Buttons, and the Scroll Bar. The usefulness
of other controls, such as the Canvas, the Page Panel, and the Timer, may
not be immediately apparent. These controls and others will be covered in
Chapter Six. For the Hello World application, the only control required is the
Default Button. Find the Default Button in the controls list and drag it onto
the window in the Layout Editor. Dragging controls onto windows is a task
that you will perform repeatedly as you build your app. Once you drop the
control onto the window, you may drag it to change its position, and you
may also use the Inspector properties to modify it.
12
2) With the newly added Default Button selected, click the position. Don’t worry too much about the specific location of the button;
Inspector Button in the toolbar. just use your own judgement to design the window. Your window may look
something like this:
There are only a few properties that you will change for your Hello World
application, and in reality, they are all optional. However, you want to begin
even now to develop habits that will lead to better productivity down the
road. With that in mind, the first property you will edit is the first property in
the list: Name.
A control’s name is the way you will refer to it in your code. A control’s
name may not include spaces or punctuation, aside from the underscore
character. It is highly advisable to give each control a name that will remind
you of its purpose. In this case, the name HelloButton will remind you that
this button will say, “Hello.” The Xojo language is not case sensitive, so if
you prefer to use all lower case letters for the name, Xojo will not object.
The second property you will modify is the PushButton’s Caption. While the
control’s name is how you as the developer will refer to the control, the
And here is a closer (partial) view of the Inspector:
caption is how the end user of your application will see it. In the case of a
Button, the caption will be the visible text on the button itself. Change
HelloButton’s caption to “Say Hello” in the Appearance section of the
Inspector. The caption can include spaces and punctation.
If you prefer to modify your Button’s position visually, you may drag it into
position manually and use the guide lines that appear to help it “snap” into
13
8) With the Action event highlighted, click OK to display the
Code Editor. This is the code you’ll use:
MsgBox("Hello, World!")
Your window should appear, complete with your “Say Hello” button.
Clicking the button, however, does not bring up a “Hello, World!” message.
To accomplish that, you need to add some code to the Button.
7) Quit your running app to return to Xojo. As you enter code into the Code Editor, you may notice that Xojo helpfully
autocompletes as you type. Xojo’s autocomplete is a great way to learn
When you see Layout Editor again, double click on HelloButton. Xojo will
more about the language, since you can begin typing a few letters to see
present you with a list of events to which you can add code. Select the
what suggestions appear. In addition, help appears at the bottom of the
Action event (the code in the Action event is run whenever the Button is
window, offering information about the method or function to which the
clicked). You will see other events listed as well, such as KeyDown,
mouse is currently pointing. This is another great way to learn more about
LostFocus, Open, and others, but for now you will only need the Action
the Xojo language.
event (events will be explained in greater detail when controls are
discussed in Chapter Six). As for what you actually typed in, you entered two things: a method and a
parameter. These terms will be explained in detail in Chapter Three, but for
now, just know that a method in Xojo is simply a way of telling the
computer to do something. A parameter for that method gives the
14
computer additional details about what you want. In essence, the method is
what you want to do, and the parameters are how to do it.
The method you’re running is MsgBox, which you can think of as shorthand
for Message Box. MsgBox takes a piece of text and displays it to the end
user of your app. The piece of text in question in this example is “Hello,
World!”.
Once again, your window should appear, complete with your “Say Hello”
button. This time, clicking the button does indeed display a “Hello, World!”
message. Congratulations! You’ve built and run your first Xojo app.
If you are familiar with other programming languages, you may notice
some differences from some of them. First of all, many languages
require a semicolon at the end of a line, rather than relying on white
space and/or line breaks to indicate the end of a line. Xojo code
should never end with a semicolon - Xojo will actually use the Syntax
Help area at the bottom of the window to warn you if you type a
semicolon out of habit.
15
1.5 Swatting Bugs
Now that your first application is successfully running, this section
will give you a very brief introduction to the Xojo debugger. Note
that while the debugger is a critical part of Xojo, it will not have an
entire chapter dedicated to it. Instead, as other concepts are
introduced, you will gradually learn more about the debugger. For
now, you will see two ways to access the debugger: one
intentional way and one accidental way.
First, the intentional way: back in the Code Editor, find the place
you entered the MsgBox line earlier (if your Hello World
application is still running, you will need to quit or exit from it).
Change the code in HelloButton’s action event to look like this:
Break
MsgBox("Hello, World!")
The Break keyword causes your app to pause, but not stop, and This is Xojo’s debugger. With your current project, there is not
displays Xojo’s debugger. With the Break keyword in place, run much to see, but as your projects become more involved, the
your project. When you click HelloButton, you will see a screen debugger can provide you with a wealth of information about your
similar to the one below: application while it is running. In the screenshot above, note that
the currently executing line is highlighted (the Break keyword).
The pane in the lower right portion of the window provides you
with a hierarchical view of your app’s variables and properties.
16
Press the Stop button on the Editor Toolbar to stop execution of
your app and return to editing your project.
Now that you have seen one way to access the debugger
intentionally, let’s look at an accidental way. This example is,
admittedly, contrived, but it should show you an important aspect
of using the debugger.
Dim p As PushButton
p.Push
For now, you need not worry about what the above code is even
attempting to do. Simply run your project again and press
HelloButton. The debugger should appear again, but with a
slightly different look:
The red bug icon indicates where the error has occurred. A
glance at the variables pane shows that P, the PushButton, is Nil.
The meaning of this will become clear in later chapters, but in
essence, you have attempted to access something that simply
does not exist yet.
17
Bugs? You may wonder why programming errors are called bugs. In
the early days of computing, computers relied heavily on vacuum tubes
for their operating. These computers often filled an entire room.
Vacuum tubes generate both heat and light, and they would often
attract moths, which would interfere with the computer’s operation. At
that point, someone would have to go in and “debug” the computer.
18
Chapter 2
Introduce
Yourself
CONTENTS
1. Chapter Overview
For example, you may have a variable named MyAge. Its type
could be integer, or a whole number, and its value might be 16.
20
see in later chapters), in general, specific names are more
2.2 A Place For Your Stuff practical. A variable name should indicate its purpose to you at a
glance.
As noted above, a variable is a way for you as the developer to
refer to a location in the computer’s memory that holds a value Second, when it comes to capitalization, no way is the right way.
you may need to access, either to read it or change it. In order to Some developers prefer camelCase (also known as medial
refer to this memory location, you will begin by choosing a name capitals), some prefer names_with_underscores, and some use
for your variable. Establishing good variable naming conventions lowercasewithnopunctuation (although many find this style to be
early in your programming experience will help you tremendously difficult to read). None of these approaches is wrong, but
down the road. Naming variables can be difficult, but by keeping whatever you decide to use, be logical and, most importantly, be
a few guidelines in mind, you will be able to come up with a consistent. In this book, camelCase variable names will be used.
convention of your own.
Third, some developers prefer to use the variable name to
Bear in mind that these are simply conventions. Each person indicate its type, although this is admittedly far from universal.
needs to develop a naming convention that best fits his or her Examples would include nameString, birthDate, and favoriteColor.
coding style. This is not part of the convention we will be following in this book,
but you are free to follow it in your own code and projects.
First, pick variable names that are specific and descriptive. For
example, the sample project you will build later in this chapter will Finally, note that as you expand your knowledge of Xojo, you will
have a variable that needs to store the end user’s first and last be able to apply these same guidelines and conventions to other
name, so that variable is called fullName. If you needed to aspects of your code, such as function names and custom
differentiate between different people’s names, you may have classes.
variables called employeeFullName and supervisorFullName.
Now that you have some ideas on variable naming, it’s time to
Don’t worry about using long names for your variables, since
take a look at how you can tell Xojo about these names. To do
Xojo’s autocomplete can help with the typing later on. Avoid
that, you will use the Dim keyword.
generic names. Working under a deadline, you may be tempted to
use a single letter for a variable name. While this may be To use an example from above, you may have a variable called
appropriate for certain counting and looping functions (as we’ll FullName that you will use to store someone’s name. Its data type
21
will be string (which will be explained in Section 2.3). To create instantiates, or creates an instance of, your variable. Consider the
this variable, enter this line into Xojo: following lines:
This simple line accomplishes quite a lot. As was explained With that line, you have set aside space in memory for your
above, it reserves space in the computer’s memory for the variable, you have named it (today), and you have told Xojo what
information you want to store. It also sets aside a specific, kind of data you will be working with (a date value). What you
memorable name that by which you can refer to it. Finally, it tells have not done, however, is create the date object itself. So if you
Xojo what type of data you’ll be storing (in the above example, a attempt to access one of Today’s properties, such as its
string, or text data). ShortDate property, before continuing, you will encounter a
NilObjectException such as the one demonstrated at the end of
Chapter One.
Dim is actually short for “dimension,” and refers to the early days of
computers when developers had to set aside memory and reserve it for To instantiate your variable, use the New keyword:
use in their apps. These days, memory certainly is not at as much of a
premium, but you still need to tell the computer to reserve space. today = New Date
23
2.3 Common Data Types
You may have noticed “data types” being mentioned quite a bit in
the past few pages, but what is a data type? Simply put, a data
type is a form of information that behaves in a certain way and
has certain characteristics. In this section, you will learn about
some very common data types. Most programming languages
use the same basic set of data types.
STRINGS
One of the most common data types you will encounter is the
string. A string is simply a piece of text. It can be of any length
(the maximum size of a string is limited only by the computer’s Whenever you enter string data into Xojo, it must be surrounded
memory) and can contain any data that can be represented by by double quotes:
letters (of any language), numbers, and punctuation. To create a
myName = "Elvis Presley"
string in Xojo, simply use the Dim keyword:
Dim myName As String If you have a string that already contains double quotes, you must
“escape” the quotes by doubling them:
Strings are one of a small set of data types that do not need to be
myName = "Elvis ""The King"" Presley"
instantiated. As soon as the line of code containing the Dim
keyword is executed, the string is created in memory, although it
A doubled double quote may look odd, but the extra double
is empty.
quote tells Xojo that it is part of your string data and does not
denote the end of your string.
24
Strings can sometimes be a source of confusion for new INTEGERS AND DOUBLES
developers. Because they may contain any textual data, their An integer is a whole number, so it contains no precision beyond
data can sometimes look like data of another type. Consider the its decimal point. Usually an integer can be positive or negative.
following:
The maximum and minimum values of an integer depend on the
Dim myAge As String computer. On a 32-bit system, an integer can be as low as
myAge = "18"
-2,147,483,648 and as high as 2,147,483,647. That’s a range of
4,294,967,295 possible values.
If you look at the value of the myAge string, it appears to us as
humans to be numerical data: 18. However, to the computer (and Most modern computers are 64-bit. A 64-bit computer can hold
the Xojo compiler), it is not. It is simply a series of bytes that an integer as low as -2^63 and as high as one below 2^63.
represent a 1 followed by an 8. Before using this data, which
appears to be numerical, as part of a mathematical function, you
need to perform an intermediate step. To retrieve its value as a
number that the computer will recognize as such, use the CDbl
function:
25
Since both integers and doubles are numeric data types, you may
use them in mathematical operations without issue:
If you are on a 32-bit computer, that will give you a 32-bit integer.
Appropriately enough, if you are on a 64-bit computer, that will Dim oneNumber As Integer
give you a 64-bit integer. Dim anotherNumber As Integer
Dim theResult As Integer
If you wish to be more specific about the type of integer you oneNumber = 5
anotherNumber = 10
need, you may do so:
theResult = oneNumber + anotherNumber
26
Which method you should use depends on your own preferences
and on which way seems more readable to you.
BOOLEANS
27
Dim today As Date Dim thisMonth As Integer
today = New Date today = New Date
thisMonth = today.Month
So far you have seen how to set these properties, but you may
also retrieve them from the date object:
28
There are also some string properties that can be accessed.
These are very useful for displaying dates to your end users. They
include AbbreviatedDate, ShortDate, ShortTime, LongDate, and
LongTime. These strings will vary based on the settings and
locale of the end user’s computer.
One last property of the date object that will be discussed in this
chapter is TotalSeconds. TotalSeconds is a double, and it
represents the number of seconds passed between midnight on
January 1, 1904, and the date object’s value. TotalSeconds may
be set manually if you know the right value. This makes
TotalSeconds an easy way to set all information the date in one
line of code.
To change your color in code, you must understand a few basics
COLORS about how Xojo stores colors. A color has three properties that
It may be odd to think of a color as a variable, but Xojo does. To will be discussed here: Red, Green, and Blue. Each of these is an
create a color variable: integer that may be anywhere from zero to 255. The higher the
value, the more that shade is present in the color. For reference,
Dim myColor As Color the color black would have zero for each property, while white
would have 255 for each property. Pure red would have 255 for
As with strings, integers, and doubles, colors do not need to be Red, zero for Green, and zero for Blue. Purple would have 255 for
instantiated. When created, a color defaults to black. Red, zero for Green, and 255 for Blue.
You may change a color in your code or by asking the user to To set these properties in code, you may simply enter a value for
select a color. You will see both methods. each, using the RGB method:
30
dDay.Month = 6
2.4 Putting Variables To dDay.Day = 6
Use You may also set its TotalSeconds property (474,736,043 seconds
after January 1, 1901, is January 16, 1919):
Now that you know the basics of creating variables, it’s time to
learn about getting, setting, and comparing their values. Dim prohibitionDate As Date
prohibitionDate = New Date
For the most part, to set a variable’s value, use the equal sign. prohibitionDate.TotalSeconds = 474736043
Depending on the data type, you may or may not need to use
quotation marks. They are required for string data, but should be Another way to set date’s value is by using its constructor. A
omitted for numeric data types and booleans. constructor is a special method that runs when a new object is
instantiated. Consider the syntax you have been using to
Dim meaningOfLife As Integer
instantiate dates:
Dim chapterTitle As String
Dim thisIsEasy As Boolean
meaningOfLife = 42 Dim nineEleven As Date
chapterTitle = "Introduce Yourself" nineEleven = New Date
thisIsEasy = True
If you know the date values, you may assign them when you
As mentioned above, dates and colors are a different story. A instantiate the date with this syntax:
date’s value cannot be set directly (unless you have another date
Dim nineEleven As Date
object already in existence, in which case you still have the issue
nineEleven = New Date(2001, 9, 11)
of the original date needing a value to begin with). To set a date’s
value, you may set each of its properties (year, month, day, hour,
The date’s constructor can take up to seven parameters. In the
minute, second):
above example, you only used three: year, month, and day. The
Dim dDay As Date year must be specified, but the month and day may be left out, in
dDay = New Date which case they are assumed to be 1; everything else that is left
dDay.Year = 1944 unspecified is assumed to be zero. The parameters are, in order,
31
year as integer, month as integer, day as integer, hour as integer,
When you see a line of code that starts with “//”, that line is a
minute as integer, second as integer, and GMTOffset as double
comment. A comment is there for the developer’s reference and will
(the GMTOffset is used to store time zone information, but you
not be part of the finished application.
can safely ignore that for now).
Colors may be set by assigning each of the color’s RGB A piece of code that executes a formula or function as seen
properties: above is called an expression. Expressions may also be algebraic
and use the same variable multiple times:
Dim logoBackgroundColor As Color
logoBackgroundColor = RGB(255, 0, 255)
Dim theAnswer As Integer
theAnswer = 25 + 35
Of course, programming is typically more complicated than //theAnswer is now 60
theAnswer = theAnswer + 10
simply assigning values as you have seen in these examples so
//theAnswer is now 70
far. Quite often, performing a calculation is involved. For numeric
data, Xojo supports the common mathematical operations that
Division is slightly more complicated. There are three operators
you would expect. Addition is performed with the + (plus sign)
related to division: / (forward slash), \ (backslash), and Mod. The
operator, subtraction is performed with the - (minus sign)
most commonly used is the forward slash, which is used for what
operator, and multiplication is performed with the * (asterisk)
is known as floating point division:
operator. If you have done any mathematical work on a computer,
these should be familiar to you. Here are some code examples: Dim exactAnswer As Double
exactAnswer = 5 / 2
Dim unitCost, quantity, totalCost As Double //exactAnswer is now 2.5
unitCost = 25
quantity = 4
With the backslash, Xojo performs integer division, which does
totalCost = unitCost * quantity
//totalCost is now 100 not account for fractional values:
operation:
Getting a variable’s value is typically an equally simple matter.
Dim leftoverValue As Double When debugging, an easy way to display a variable’s value is to
leftoverValue = 5 Mod 2
use the MsgBox function that you used in Chapter One. Since the
//leftoverValue is now 1,
//since 5 divided by 2 is 2 with a remainder of 1 MsgBox takes a string as its only required parameter, displaying
the value of a string is trivially easy:
Mod can also be useful for determining whether an integer is
Dim theGreeting As String
even or odd. If your integer Mod 2 is equal to 1, the number is
theGreeting = "Hello!"
odd. If the answer is zero, the number is even. MsgBox(theGreeting)
33
The code above stores the value of the integer in a string and Character Description
then displays that string to the user in a message box. # Placeholder that displays the digit from the value if it
is present.
One downside of using Str is that it gives you as the developer no If fewer placeholder characters are used than in the
passed number, then the result is rounded.
control over how your data will be formatted. For example, a large
0 Placeholder that displays the digit from the value if it
number may be displayed in scientific notation, or you may wish is present.
If no digit is present, 0 (zero) is displayed in its place.
to limit the number of decimal places that are displayed. In such
. Placeholder for the position of the decimal point.
cases, the Format function is useful.
, Placeholder that indicates that the number should be
formatted with thousands separators.
Format takes two parameters. First is the numeric variable
(integer or double), and second is the format specification. A % Displays the number multiplied by 100.
format specification is a string that describes how the number + Displays the plus sign to the left of the number if the
number is positive or a minus sign if the number is
should be displayed. For example, if you had the value .25 and negative.
wanted to display it as a percentage, you would use “#%” as the - Displays a minus sign to the left of the number if the
number is negative. There is no effect for positive
format specification: numbers.
34
Here is a code example from the chart above:
So far you have seen a few ways to convert numbers into strings
for display, but you can also convert strings into numbers to use
in calculations. As mentioned earlier in the chapter, the best way
to accomplish this is by using the CDbl function:
Now that you have learned some things about variables, as well
as getting and setting their values, it’s time to build this chapter’s
sample project, called “Introduce Yourself.”
35
3) From the Library, drag a Label onto Window1.
2.5 Hands On With 4) Switch to the Inspector and set the Label’s text property to
In Chapter One, you used the Inspector to set the properties of a button on Control Name Text Caption
a window. You may also use the Inspector to set the properties of the Label LastNameLabel Last Name: N/A
window itself. With no objects on the window selected, the Inspector will
Text Field LastNameField N/A N/A
modify the window’s properties. You are going to set three of the window’s
Label BirthYearLabel Birth Year: N/A
properties: title, width, and height.
Text Field BirthYearField N/A N/A
2) Set Window1’s title to “Introduce Yourself”.
Default IntroduceButton N/A Introduce
Button
Note that the window’s title and name are different. The title is what
appears to your end user at the top of the window in your running
application. The name is how you as the developer refer to it in your code. 8) Position and size your controls using your own creativity.
In a more complex application, it is always recommended to give your
When all of your controls have been added to Window1, your window may
windows meaningful titles, but for your purposes in the project, setting just
be similar to the screenshot below.
the title will be sufficient.
36
FullName is the string you will use to store the user’s concatenated first and
last names. CurrentAge will store the user’s age in years. Today will hold the
current date (note that the code above has already instantiated it, so it
already contains data about the current date). Finally, theMessage is a
string that will put everything together to display to the end user.
fullName = FirstNameField.Text ¬
! + " " + LastNameField.Text
This code concatenates your user’s first and last names. To do this, you will
Now that your interface is complete, you will need to write some
access the Text properties of your TextFields. The Text property holds
code to make your application do something. To add code, whatever is visible in the TextField. It is accessed using what is known as
double click on IntroduceButton and choose the Action event to dot notation, which you have already used when getting and settings
open the Code Editor. properties for dates and colors. Dot notation is a way of accessing
properties by using the object’s name, followed by a dot, followed in turn
At the beginning of the chapter, you learned what this application by the name of the property, such as FirstNameField.Text. This should be
will do. As a reminder, it will calculate the end user’s full name and familiar to you from looking at string concatenation earlier in this chapter.
his or her age at the end of the current year and then display this
3) To determine the user’s current age in years, enter this code:
information to the user. You will need four variables to make this
happen. currentAge = Today.Year - CDbl(BirthYearField.Text)
1) In the Code Editor, add the following variables: Note: for the purposes of this project, you will ignore the month of birth and
simply calculate the age in years at the end of the current year; taking
Dim fullName As String
months into consideration is not difficult, but it involves some skills that
Dim currentAge As Integer
have not yet been covered. You will retrieve the data entered by the user
Dim today As New Date
into BirthYearField. Remember, however, that BirthYearField.Text will give
Dim theMessage As String
you a string, which you will need to convert into numeric data, using CDbl.
You will subtract that number from the current year to determine the user’s
current age in years.
37
4) Add this line of code: 6) Display theMessage to the end user using this line:
You now have all of the data that you need to display to the end user. The Altogether, your code should look like this:
next step is to assemble it into a message to display to the end user. You
will again do this through string concatenation. To make your message Dim fullName As String
more pleasing to the eye, you will also add a line break after the user’s full Dim currentAge As Integer
name. This is accomplished using the EndOfLine class. Dim today As New Date
Dim theMessage As String
fullName = FirstNameField.Text ¬
For historical reasons, OS X, UNIX, and Windows all denote line ! + " " + LastNameField.Text
endings in different ways. To account for this, Xojo’s EndOfLine class currentAge = today.Year - CDbl(BirthYearField.Text)
will automatically use the correct line ending for the current platform, theMessage = "Your name is " + fullName + EndOfLine
although a platform-specific line ending can also be used when
theMessage = theMessage + "and you will be "
theMessage = theMessage + Str(currentAge)
necessary. For the most part, simply use EndOfLine and you should theMessage = theMessage + " at the end of the year "
be fine. theMessage = theMessage + Str(today.Year) + ".
MsgBox(theMessage)
38
9) Quit your application.
39
This will tell Xojo to stop running your application before the
2.6 Advanced Bug CurrentAge line is executed. To demonstrate, run your project
now and fill in your name and birth year. When you press
Swatting IntroduceButton, you will see the debugger:
In Chapter One, you got a brief look at Xojo debugger, using the
Break keyword. With the current “Introduce Yourself” project, this
is a good time to take a slightly deeper look into breakpoints.
40
The string called FullName is already assembled, but the integer
CurrentAge is zero. That’s because this line of code:
Click on that button to step to the next line of code. The next line
will now be highlighted in gray and the variables pane will change
to show the calculated value of CurrentAge. You may continue to
press the Step button to walk through your code. If you are ready
to return to your running application, press the Resume button in
the debugger toolbar.
41
Chapter 3
Where Do We
Go Now?
CONTENTS
1. Chapter Overview
2. If... Then
3. Select Case
4. For... Next
5. Do... Loop
6. While... Wend
For this chapter’s project, you will build a custom font previewer.
By default, it will list all fonts installed on the end user’s computer.
When a font is selected, your application will show a preview of
that font. Your application will also allow us to search for specific
fonts as well. A screenshot is provided below.
43
come from the user checking a checkbox or clicking on a radio
3.2 If...Then button.
The most common logic problem you will encounter as a Note that the If statement follows a certain structure. The line
developer is checking whether one value matches another value. always begins with If, followed by the expression to evaluate,
For example, you may need to check if a boolean is true or false, followed by Then. The next section of code is always
or you may need to check if an integer is greater than or equal to automatically indented by Xojo, and it will execute only if the
100. You may even need to check whether a string contains expression evaluates to true. Following that code is the final line:
another string. This type of logic is performed using If. End If.
Note that if you are checking the value of a boolean, you can omit
Most other programming languages, such as C, C++, PHP, Java, and the “ = True” or “ = False” part of the expression:
Objective-C, feature the If keyword. Some languages use a slightly
different syntax, but the end result is the same. Once you learn how to Dim theLightsAreOn As Boolean
use If...Then in Xojo, you will be well on your way to using it in any theLightsAreOn = True
other language. If theLightsAreOn Then
! //React here to the fact that the lights are on
End If
To use an example from above, imagine that you needed to check
whether a boolean was true or false:
If you have worked with any C-based languages in the past, you may
Dim theLightsAreOn As Boolean
notice something interesting about Xojo. In most C-based languages,
theLightsAreOn = True
If theLightsAreOn = True Then you must use a double equal sign to compare data (If MyVar1 ==
! //React here to the fact that the lights are on MyVar2), whereas here you are using only one equal sign. Xojo
End If overloads its equal sign operator so that it can be used for comparison
or for setting values. In fact, if you enter “==” into Xojo, it will issue a
What does theLightsAreOn mean? theLightsAreOn is a boolean warning.
variable, which you learned about in the previous chapter. Its
value may come from somewhere else in your code, or it may
44
In the above example, you only tell Xojo what to do if If you want your comparisons to be inclusive, you may use
theLightsAreOn is true. There are many times when you need to operators for “greater than or equal to” and “less than or equal
react accordingly if a value is false. To do so, use the Else to” in your expressions:
keyword:
If myAge >= 17 Then
Dim theLightsAreOn As Boolean ! MsgBox "You are old enough to vote"
theLightsAreOn = True Else
If theLightsAreOn Then ! MsgBox "You are not yet old enough to vote"
! //React here to the fact that the lights are ON End If
Else
!
OFF //React here to the fact that the lights are You may use any data type with If. Here is an example using
End If
strings:
You are, of course, not limited to checking only boolean values. If Dim myString As String
you needed to check an integer, you may certainly do so: myString = "Hello"
If myString = "Hello" Then
Dim myAge As Integer ! MsgBox "We have a match!"
myAge = 16 Else
If myAge > 17 Then ! MsgBox "We do not have a match!"
! MsgBox "You are old enough to vote" End If
Else
! MsgBox "You are not yet old enough to vote" Xojo’s string comparisons are not case-sensitive. Because of this,
End If
the above example could be rewritten as below with identical
functionality:
In the above example, you are using the greater than symbol
instead of the equal sign. When using greater than or less than, Dim myString As String
remember that they are not inclusive of the number you are myString = "Hello"
If myString = "hello" Then
comparing against. In other words, in this example, if myAge were
! MsgBox "We have a match!"
equal to 17, the message box would read, “You are not old Else
enough to vote”. ! MsgBox "We do not have a match!"
45
End If string to be searched (sometimes referred to as the haystack).
The third parameter is the string to search for (sometimes referred
In a case-insensitive system, a lower case “a” will match an upper to as the needle). The value returned by InStr is an integer that
case “A” - the characters are considered to be equal. If you need indicates where in the source string the found string occurs. If it is
to perform a case-sensitive string comparison, you may use the not found within the source string, InStr will return zero. Any non-
StrComp function. zero result indicates that the string has been found.
For example, assume that you have asked the end user for a
short paragraph about his or her background and that you need
to issue an error message if the user includes the word “ninja”
anywhere in his or her bio. Your application’s interface would
Often, you’ll need to determine whether one string contains likely contain a TextField called BioField, where the user would be
another string. For example, you may need to check if some data expected to enter his or her biographical data.
entered by the user contains a particular keyword. This can be
accomplished with the InStr function. InStr takes two or three If Instr(BioField.Text, "ninja") > 0 Then
! //Issue a ninja alert!
parameters and returns an integer. The first parameter is an Else
integer, and it is optional. It indicates the position within the string ! //This is a ninja-free zone
to be searched that Xojo should begin searching. It defaults to End If
however, is verify that the data could, in fact, be numeric. Xojo such as year, month, day, etc. Or if you need to check a date to
has a function called IsNumeric that will check to see if a string’s see if it is part of a given year:
IsNumeric is not limited to simple integers. It will correctly The code above uses “Or” to separate your conditions, so the
interpret floating point numbers and even scientific notation. expression will evaluate to true if either condition is met. You may
also use “And” to separate conditions, in which case both
If you need to compare date values, the best way is to compare
conditions will need to be true; if only one is true, the statement
their TotalSeconds properties:
will evaluate to false.
If today.TotalSeconds > yesterday.TotalSeconds Then
47
If today.Year = 2012 And today.Month = 12 Then ElseIf Instr(BioField.Text, "pirate") > 0 Then
! //The world may be ending really soon. Be ! //Issue a pirate alert!
!
cautious.
ElseIf Instr(BioField.Text, "zombie") > 0 Then
End If ! //Issue a zombie alert!
Else
! //We are safe from perceived threats
End If
Note that Xojo will jump to the end of the If statement as soon as
one of the conditions is met. In other words, if the code above
encounters a robot, the user’s bio will not be checked for
references to pirates and zombies. If you need to have a separate
check for each, you must use a separate If statement for each.
There will be times when you will need to check for multiple
conditions and react accordingly. For example, a few paragraphs
above, you checked for ninjas. What if your code also needed to
be aware of pirates, zombies, and robots? In between the If and
the End If, you may add an ElseIf. Or you may add several ElseIf
statements:
48
! MsgBox("It's October")
3.3 Select Case Case 11
! MsgBox("It's November")
Case 12
Xojo’s Select Case statement provides you as the developer with
! MsgBox("It's December")
a cleaner way to check a variable or expression for multiple Else
values. It allows you to specify each condition you wish to check, ! MsgBox("Unable to determine current month")
using the Case statement, as well as the code that should End Select
49
Some other common programming languages use “switch” instead of
“select case” for such comparisons. Aside from that minor word
change, the functionality is identical.
50
Run your project again to see the difference.
3.4 For...Next Your counter can also count down instead of up:
Any time that you need to perform a similar operation on a series
of variables, a For...Next loop is an easy way to do it. In its Dim counter As Integer
For counter = 10 DownTo 1
simplest form, a For...Next loop simply steps through a list and ! MsgBox(Str(counter))
executes whatever code you specify. Every For...Next loop needs Next
a variable to use as a counter.
Your counter may also skip numbers, using the Step keyword:
Create a new desktop project in Xojo. In the Layout View of
Window1, double click on the window to open its Code Editor. Dim counter As Integer
Locate Window’s1 Open event and enter this code: For counter = 1 To 10 Step 2
! MsgBox(Str(counter))
Dim counter As Integer Next
For counter = 1 To 10
! MsgBox(Str(counter)) Nearly every time that you use a For...Next loop, your code will do
Next
something much more interesting than simply pop up a message
box. There are many times when you will have a group of similar
Next, run your project. You should see 10 message boxes, for
objects. You will often store these in an array. You will learn about
number 1 through number 10. After dismissing all 10 message
arrays in depth in Chapter Five, but for now, just think of an array
boxes, quit the application.
as a numbered list of similar objects or variables. This section and
You are not limited to using the counter alone. Change your code the next few sections will cover how to step through groups of
to the following: objects, but rather than get into the details of how arrays work at
this point, you will use an easy to access array that is built into
Dim counter As Integer your computer: your fonts. Xojo has a built in function called
For counter = 1 To 10
FontCount, which returns the number of fonts you have installed.
! MsgBox(Str(counter * 2))
Next You will be using that function to gather your group of objects,
which in this case will be a list of fonts.
51
1) Create a new desktop project in Xojo.
2) Open up Layout View for Window1 and add a TextArea This loop will continue to add font names to MyFontList. When the list is
control to the window. complete, you will display it in the TextArea.
Size it so it takes up almost all of the window: Don’t worry about how Font(Counter) works. That will become clear in
Chapter Five. For now, just know that it gives you the name of the next font.
The font name is followed by a line break.
Me.Text = myFontList
All together, the code in your TextArea’s Open event should look like this:
After a few seconds, you should see a list of your computer’s fonts
4) Set up the For...Next loop. displayed in the TextArea.
myFontCount = FontCount - 1
Remember that FontCount is a function built into Xojo. One thing
to keep in mind is that every time this loop runs, that function will For counter = 0 To myFontCount
! myFontList = myFontList ¬
also be run. If you have a fast computer or few fonts, you may not
! ! + Font(counter) + EndOfLine
notice the speed hit, but there is a way to optimize this code. Add Next
a new variable:
Me.Text = myFontList
Now your loop will refer to the cached value instead of running the
FontCount function every time it runs. Your new code should look like this:
53
! MsgBox(Str(x))
3.5 Do...Loop Loop
Another kind of loop that is available in Xojo is the Do...Loop. A Run the project again, and no message boxes will appear. This is
Do...Loop is useful when you need to check for a certain because the condition (x > 100) has already been met, so the
condition each time the loop runs. The Do...Loop has two forms, loop exits. However, if you change the loop again, you should see
one of which does not guarantee that the loop will be run at least a different result:
once, and one that does make such a guarantee.
Dim x As Integer
Here is an example of a Do...Loop (as with all of the exercises in x = 101
this book, feel free to create a new desktop project in Xojo and Do
! x = x * 2
enter this code in Window1’s open event to try it out):
! MsgBox(Str(x))
Loop Until x > 100
Dim x As Integer
x = 1
Do Until x > 100 This time, one message box will appear containing the number
! x = x * 2 202. When the Until keyword is at the end of the loop, your loop
! MsgBox(Str(x))
is guaranteed to run at least once. If the Until keyword is at the
Loop
beginning of the loop, the loop may not run at all, depending on
whether the condition is already met.
If you run this project, you will see a series of message boxes,
each a number twice as large as the preceding number: 2, 4, 8,
16, 32, 64, 128. After you reach 128, the loop stops, because you
told the loop to end once x is greater than 100. Now let’s try a
slightly different version of this loop. Set x to 101:
Dim x As Integer
x = 101
Do Until x > 100
! x = x * 2
54
3.6 While...Wend
A third type of loop that you will learn about in this chapter is the
While...Wend loop (Wend is shorthand for While End). This is
similar to the Do...Loop. Here is a code example:
Dim x As Integer
While x < 100
! x = x + 1
Wend
MsgBox Str(x)
When run, this code will display a message box containing the
number 100. The While...Wend loop is particularly useful when
dealing with databases, as you will see in Chapter Twelve.
55
Me.Text = myFontList
3.7 Exit and Continue
If you run this project, the TextArea that used to contain your full
There may be situations in which your loop is searching for a
font list will now only list fonts up to (and excluding) Courier New.
matching value and can stop searching when the first match is
If you want Courier New to be included in the list, you would
found. For this, the Exit statement is used. To use a modified
move your If...Then statement to after the line that builds your list
version of your font example from above, assume that you want
of fonts:
to exit a For...Next loop once you have located the font Courier
New. Add these three lines of code, a simple If...Then statement: myFontList = myFontList + Font(counter) + EndOfLine
If Font(counter) = "Courier New" Then
If Font(counter) = "Courier New" Then ! Exit
! Exit End If
End If
Dim counter As Integer Another way to modify the behavior of your loops is with the
Dim myFontList As String
Continue statement. Suppose that you had a loop such as this
Dim myFontCount As Integer
(this is pseudo-code and is not meant to be run):
myFontCount = FontCount - 1
Dim x As Integer
For counter = 0 To myFontCount For x = 1 To 100
! If Font(counter) = "Courier New" Then ! DoMyFunction(x)
! ! Exit ! DoAnotherFunction(x)
! End If ! DoAThirdFunction(x)
! myFontList = myFontList ¬ Next
! ! + Font(counter) + EndOfLine
Next
56
Assume that DoMyFunction, DoAnotherFunction, and
DoAThirdFunction are functions that will do something interesting
with your integer x. But suppose that for the number 72, you only
wanted to run the first function. This code would accomplish that:
Dim x As Integer
For x = 1 To 100
! DoMyFunction(x)
! If x = 72 Then
! ! Continue
! End If
! DoAnotherFunction(x)
! DoAThirdFunction(x)
Next
The Continue statement tells Xojo to stop that iteration of the loop
and go back to the start. Here is a way to run only the first
function for even numbers, while odd numbers would have all
three functions executed:
Dim x As Integer
For x = 1 To 100
! DoMyFunction(x)
! If x Mod 2 = 0 Then
! ! Continue
! End If
! DoAnotherFunction(x)
! DoAThirdFunction(x)
Next
57
3.8 Hands On With Loops
For this chapter’s project, you will be building the font previewer
that you saw at the beginning of the chapter.
TextArea PreviewField Since your application will be previewing fonts, your end user will need
some sample text to look at. This is a fairly short sentence that still
ListBox FontListBox
displays all the letters of the english alphabet. Also, set its TextSize
property to 36.
Design your interface as you see fit, using your own creativity. You may
want to use this interface as a guide: With the controls added, your window may look like this:
58
myFontCount = FontCount
Most of that code should look familiar. You are using the FontCount
function to determine the number of fonts on the computer and looping
through them with a For...Next loop. On each iteration of the loop, you add
a new row to FontListBox. Note that in any of a control’s events, using “Me”
refers to the control. So this line:
Me.AddRow(Font(counter))
Your interface is now complete. This project will have much more code than
the previous chapter’s project, but it will also do a lot more. The ListBox, is equivalent to this line:
which was named FontListBox, will display a list of all of the fonts installed
on the computer. Clicking on the name of one of those fonts will update FontListBox.AddRow(Font(counter))
PreviewField and change the font to the selected one. The small TextField
above FontListBox, which was named SearchField, will allow the end user
Using Me instead of the control’s name is simply shorthand, although it can
to search for fonts on the computer. The user will be able to enter all or part
come in very handy if you ever change the control’s name later on.
of a font’s name, at which point FontListBox will be updated to show only
those fonts that match. 6) Add the Change event handler to FontListBox and add this
code:
With that in mind, the first thing you need to do is build your font list. You
will be dealing with more controls and events than you have learned about
If Me.ListIndex <> -1 Then
so far, but don’t be concerned with the technical details at this point. These
! PreviewField.TextFont = Me.List(Me.ListIndex)
issues will be covered in depth in Chapter Six. To build your font list, double
End If
click on FontListBox to open the Add Event Handler window. Choose the
Open event and click OK.
The Change event occurs when the user selects or deselects a row in the
5) In the FontListBox’s Open event add the following code: ListBox. Because the user could be deselecting, you need to check
whether or not a row is selected. Again, don’t worry too much about how
Dim counter, myFontCount As Integer the code works. It will become clear in later chapters.
59
7) Run the project and try selecting different fonts. End If
9) Double click on SearchField and add the TextChange event There are two paths that this code can take. First, if SearchField is not
handler with this code: empty, you will loop through your fonts and display only those whose
names contain the SearchString. The following code will accomplish that:
Dim searchString As String
Dim counter, myFontCount As Integer searchString = Me.Text
For counter = 0 To myFontCount - 1
! If InStr(Font(counter), searchString) > 0 Then
This event occurs whenever the text inside the TextField is modified,
! ! FontListBox.AddRow(Font(counter))
whether by typing, deleting, or pasting. The code in this event will be similar
! End If
to the code in FontListBox’s Open event, but you will need to do some Next
checking. This code starts by declaring your variables.
You have your SearchString, plus two integers: Counter and MyFontCount, On the other hand, if SearchField is empty, you should assume that the end
which should be familiar from the above examples. user wants to see all of the fonts installed on the computer. Here is the
code for that (note that it is very similar to the way you originally filled up
10) Before continuing, save your FontCount: FontListBox):
60
When all is assembled SearchField’s TextChange event should look like
this:
myFontCount = FontCount
! For counter = 0 To myFontCount - 1 with that font. Entering some text into SearchField should cause
! ! FontListBox.AddRow(Font(counter)) FontListBox to display only those fonts that match. As a bonus, you can
! Next change the text used for the preview to anything you like.
End If
14) Quit your application.
13) Run your project. In this chapter, you learned several different ways to react to
different conditions in your code. Since it’s nearly impossible to
You should see an application like this:
predict every condition your application will face, these skills are
very valuable in everyday coding situations.
61
Chapter 4
Getting
Things Done
CONTENTS
1. Chapter Overview
2. Simple Methods
3. Parameters
4. Default Values
5. Comments
7. Scope
4.1 Chapter Overview
So far, you have entered code into specific events to make sure
certain things happen at certain times. This is a common way to
code, but it can lead to duplication. For example, in your Font
Previewer, you had a few lines of code whose job it was to fill up
the FontListBox with all of the fonts on the computer. This is
some of the code in FontListBox’s Open event:
statement, the code would be completely identical and would still 5) Add the sauce to the noodles
function exactly the same.
6) Top with mozzarella cheese (optional)
This violates one of the rules of programming: Don’t Repeat If I asked you for spaghetti again next week, you would know how
Yourself. to make it, whether from memory or from writing down the steps.
In other words, you would have a method for preparing spaghetti.
63
In programming, you will often write methods for accomplishing
certain tasks, especially those tasks that may need to be
performed multiple times. If you defined a method for cooking
spaghetti, that would save us time later on; instead of listing each
of the six steps, you could simply type this:
CookSpaghetti
In this chapter, you will learn about methods and functions, and
you will make some changes to your Font Previewer project to
streamline your code using methods and functions.
64
Run your project. Its behavior should be identical, because when
4.2 Simple Methods the computer reaches the line of code that says “FillFontListBox”,
it refers back to your method and runs each line of it.
As stated above, a method is simply a set of steps for
accomplishing a task. Open your Font Previewer project in Xojo Quit your application and navigate to SearchField’s TextChange
and open Window1. From the Insert menu, choose Method. Xojo event. You can also shorten that code by using your method.
will show you four fields in the Inspector for you to fill out. Change your If statement to match this:
First is the Method Name. Name your method FillFontListBox. For If Me.Text <> "" Then
now, Parameters and Return Type should be left blank and Scope ! searchString = Me.Text
! FontListBox.DeleteAllRows
should be Public. In the Code Editor in the center of the
! For counter = 0 To myFontCount - 1
Workspace window, enter the following code: !
Then ! If InStr(Font(counter), searchString) > 0
! ! ! FontListBox.AddRow(Font(counter))
Dim counter, myFontCount As Integer ! ! End If
myFontCount = FontCount ! Next
Else
FontListBox.DeleteAllRows ! FillFontListBox
For counter = 0 To MyFontCount - 1 End If
! FontListBox.AddRow(Font(counter))
Next
Run your project again, and again, it should behave identically.
Quit your application.
This code should look familiar; it’s the code you used to list your
fonts in FontListBox. Now, navigate to FontListBox’s Open event. If you look at the code in SearchField’s TextChange event, you
Delete all of the code there and enter this: still have some similarities there. The code to fill FontListBox with
only matching fonts certainly isn’t identical to your other code,
FillFontListBox
but it is definitely similar.
65
For a more concrete example, go back to your Font Previewer
4.3 Parameters project.
We’ve talked about spaghetti already. Some people, but not all, As mentioned above, in SearchField’s TextChange event, you
prefer meatballs with their spaghetti. Your theoretical have some code that isn’t a duplicate of other code, but it’s close.
CookSpaghetti method can handle the spaghetti, but how do you If you don’t have a searchString, the code does this:
tell it to add meatballs, and only some of the time at that?
For counter = 0 To myFontCount - 1
! FontListBox.AddRow(Font(counter))
Next
FontListBox.DeleteAllRows
For counter = 0 To myFontCount - 1
! If InStr(Font(counter), searchString) > 0 Then
! ! FontListBox.AddRow(Font(counter))
! End If
Next
There are only two lines of code that are different: the If
statement. You’re going to add that code to the FillFontListBox
Methods can take parameters. A parameter is a piece of data that method by giving it a parameter.
you give to a method; the method can either do something
1) Navigate to the FillFontListBox method and enter this into
directly to that piece of data or use it to determine how to the Parameters field:
function. Your CookSpaghetti method might take a boolean called
AddMeatballs as a parameter. If AddMeatballs is true, searchString As String
66
Every parameter needs to have a name and a data type, just like a variable. myFontCount = FontCount
In fact, you can think of a parameter as a variable that can be used inside
the method. If necessary, toggle the disclosure triangle next to the line that FontListBox.DeleteAllRows
says, “Sub FillFontListBox” at the top.
If searchString <> "" Then
2) Run your project. ! For counter = 0 To MyFontCount - 1
!
Then ! If InStr(Font(counter), searchString) > 0
This time, it won’t run, because you now have a programming error. You’ve ! ! ! FontListBox.AddRow(Font(counter))
told the computer that FillFontListBox has to be given a string when it runs, ! ! End If
but you haven’t given it a string. ! Next
Else
Giving a method its parameter when you run it is called “passing” the ! For counter = 0 To myFontCount - 1
parameter. You need to pass a string to FillFontListBox in two places: in ! ! FontListBox.AddRow(Font(counter))
FontListBox’s Open event and in SearchField’s TextChange event. ! Next
End If
3) In FontListBox’s Open event, you can pass an empty string.
To pass a parameter, include it immediately after the method All of the logic that was previously found in SearchField’s TextChange event
name, wrapped in parentheses, like this: is now contained in the FillFontListBox method. In changing the project this
way, you have also eliminated a lot of duplicate and near-duplicate code.
FillFontListBox("")
You can do this because you have no font names to search for or match. In
SearchField’s TextChange event, things will be a bit more complicated,
because you’re going to move most of the logic into the FillFontListBox
method. SearchField’s TextChange will now look like this:
FillFontListBox(Me.Text)
You no longer need to check for a blank string or modify your code’s
behavior or even declare any variables, because all of that will now happen
in the FillFontListBox method which you will now need to expand:
addMeatballs As Boolean, ¬
! includeGarlicBread As Boolean
Let’s expand your virtual Italian restaurant and imagine a new searchString As String = ""
method called CookLasagna. It will be similar to the
CookSpaghetti method, but meatballs won’t be an option - only That’s just two double quotes, or an empty string. That tells the
garlic bread. So your Parameters field would look like this: method that if you do not specify what the searchString should
be, it should assume that there isn’t one. Now you can change
includeGarlicBread As Boolean
the Open event of FontListBox to this:
Suppose now that the chef insisted that every patron should FillFontListBox
receive garlic bread unless he or she specifically asks for it not to
be included. You could change the Parameters field to this: Run your project. Once again, its functionality is identical to what
it was before, but you’ve streamlined and simplified your code.
includeGarlicBread As Boolean = True
What this line of code does is not only describe the parameter,
but gives it a default value. Of course, this is not limited to
boolean values:
FillFontListBox("")
69
MyLastName = NameField.Text // NOTE: use 2 fields
4.5 Comments
Note that anything entered on a line after the comment marker
You may have noticed that in a few of the examples used here,
will be considered part of the comment.
there have been lines of code that start with two slashes followed
by a note. These are comments. Comments are another way to There are times when it is helpful to turn lines of code into
simplify your code. In general, your code should be “self- comments temporarily. This is especially true when trying to track
documenting”; that is, your method names and variable names an error. You may do this manually, by typing the double slash or
should make it clear to someone reading your code exactly what the single quote in front of each line. Xojo also has a feature that
is happening. With code that you have seen so far, that has been will comment/uncomment several lines of code at one time.
relatively easy to accomplish. As your code grows more complex, Highlight the code you wish to comment out, and then choose
however, comments can become extremely valuable. Comment from the Edit menu. If the code is already commented
with single quotes, this command will uncomment it.
A comment is a special line of code that is simply for the
developer’s reference. You may need to document what a certain
variable is for or how a specific method works, or you may simply
feel the need to make yourself a note for the future.
A comment can be added in two ways: the double slash and the
single quote. They are interchangeable and can be added
anywhere in your code. You may choose to enter a full line of
comments:
70
Now the interface for your Font Previewer needs to be modified.
4.6 Functions and Return 2) Raise the bottom edge of FontListBox and add a
Values PushButton.
1) Add a new method called “GetSelectedFont” to Window1. 5) Run your project and select a font.
You can add a new method by choosing Method from the Insert menu. It 6) Click on FontButton and your message box should appear.
won’t take any parameters, but its Return Type should be String, because
7) Quit your application.
this method will return some text.
Now it’s time to simplify the code in FontButton’s Action event.
This method will find out if a font has been selected in FontListBox and if
so, return its name to us.
You have accessed the return value of the GetSelectedFont
method by using this line of code:
Dim currentFont As String
If FontListBox.ListIndex <> - 1 Then fontName = GetSelectedFont
! currentFont = ¬
! FontListBox.List(FontListBox.ListIndex)
Else While this is perfectly fine, it’s actually an unnecessary step. As
! currentFont = "" soon as your method runs, you have the return value and you can
End If use it in your code. You can almost treat the method like a
Return currentFont
71
variable. Remove all of the code from FontButton’s Action event
and enter this instead:
Run your project again, and you should see identical behavior,
but once again, with simpler code.
72
4.7 Scope
With all of these methods, you have variables all over the place in
your code. And that’s fine. But it is important to remember that
these variables are not accessible everywhere. This is because of
something called scope.
73
Chapter 5
Making A List
CONTENTS
1. Chapter Overview
3. Clearing Out
4. Managing Order
In this chapter, you will use arrays and build on your knowledge
from previous chapters to build a to do list manager. One big
difference is that this app will be a web app. Here is what you’ll
be making (this copy of the app is running in Firefox on a Mac,
but it can run in any modern browser on any operating system):
75
myArrayCount = Ubound(myStringList)
5.2 Adding To The List
As mentioned earlier, myStringList itself is not a string; it’s a list of
Creating an array is very similar to creating any other type of
strings. Because it’s not a string, you can’t use it in the same way
variable. There’s just one thing that you must add when you
you’ve been using strings up until now. For example, you can
declare your variable. Remember that you can create a string
display a string to the end user by using a message box:
using this syntax (and remember from Chapter 2 that a string is
simply a piece of text): MsgBox(myString)
You can’t display an array to the end user in the same way.
Many times, you will not know how many items are in an array. However, you can display one of the strings in your list. If you
You can ask Xojo how many items are in an array by using the wanted to display the first item in your list of strings, you could
Ubound function (Ubound is short for “upper bound”). Ubound use this code:
will return the number of the array’s highest element:
MsgBox(myStringList(0))
76
Note that the first item in an array is item number zero. There are That would give us a list with six items. As you can see, you
historical reasons why this is the case, but it’s worth keeping in create and treat arrays the same regardless of what type of data
mind, because one of the most common errors made when they hold. In a similar vein, you treat each item in an array as a
working with arrays is starting at number one instead of number normal variable of its data type.
zero. This also means that the last (highest numbered) item in the
Creating an array is one thing, but an array isn’t valuable until it
array is one less than its count. If an array has ten items, the
contains some items. You refer to an item in an array as an
highest numbered item (and its Ubound) is nine.
element. To add an element to an array (or to add an item to a
So you can treat myStringList(0) in the same way that you treat list), you may use Append or Insert.
any other string. If you want to assign a value to it, you can do so:
When you Append data to an array, the item is added to the end
myStringList(0) = "Just your average string here" of the array, and the number of items in the array (as well as its
Ubound) is increased by one:
And you can do the same with myStringList(1), myStringList(2),
Dim myStringList(10) As String
and so on. Each item in the list is just a normal variable. So in the // Ubound(myStringList) is equal to 10
case of an array of strings, each item is just a regular string. If you myStringList.Append("Hey there")
had an array of integers, each item would be a regular integer. To // Ubound(myStringList) is now equal to 11
77
// Ubound(stooges) is now equal to 2
Index Value
0 Larry
1 Curly
2 Moe
stooges.Insert(1, "Shemp")
It may not always be the case that you want to add data to the
Ubound(stooges) is now equal to three, and the array itself looks
end of the array, though. If you need to insert data at a specific
like this:
location, use the Insert method. Where the Append method only
takes one parameter (the value you wish to add to the array), the Index Value
Insert method takes two: first, an integer that specifies the item’s
0 Larry
location in the array, and then the item itself. An item’s location in
1 Shemp
the array is known as its Index. Using the Insert method will
2 Curly
increase the number of elements in the array by one, and will also
3 Moe
increase the index of each successive item by one. This is best
illustrated with a code example:
78
keyword. It operates a similar way to the Dim keyword, except
5.3 Clearing Out that it only works on a variable that’s already in existence:
As you saw in the example above, the Insert method will “shift” ReDim stooges(-1)
the other elements in the array. Another method that will shift the
elements in your array is the Remove method. This method, as The stooges array is now empty and contains no elements. Its
implied by its name, will remove an element from the array, Ubound is now negative one.
decrease the number of elements in the array by one, and
decrease the index of the remaining elements. Continuing the You may be wondering why negative one is used to ReDim an
example above: array. ReDim essentially tells the computer to reset the number of
slots that the array has, or in other words, to resize the array.
stooges.Remove(2) Negative one tells the computer that the array should contain no
elements at all. You may use other numbers with ReDim as well;
Ubound(stooges) is now equal to two, and the array itself looks whatever number you use will determine how many elements the
like this: array can hold. If you use a number greater than the current
number of elements, you will create empty slots in the array while
Index Value retaining any existing elements. If you use a number less than the
0 Larry current number of elements, any element whose index is greater
1 Shemp than your new number will be deleted.
2 Moe
79
5.4 Managing Order
Index Value
Every time you use an array, the order of the elements matters. 0 Abe
The computer will remember which element is in which slot and
1 Mary
will preserve that information. Because of this, every time you
2 Zeke
work with the same array, you can know that whatever data you
stored in the tenth slot, for example, will remain in the tenth slot An array of strings will be sorted alphabetically in ascending
until you specify otherwise. order. If your array contains numeric data, it will be sorted
numerically. When the array is sorted, each element’s index, or
But you will encounter situations in which you want to reorder the
position in the array, will be adjusted accordingly.
elements in your array. There are certainly “brute force” methods
of doing this, but Xojo includes two array functions that are very
useful for reordering arrays.
80
As with most card games, you would likely need to shuffle the
deck at some point. Assume that in your imaginary card game,
you have an array of strings called cards, which contains 52
elements (two through ten, plus Jack, Queen, King, and Ace for
each of the four suits). To shuffle the deck:
cards.Shuffle
The cards will now be in random order. That’s all there is to it.
Shuffle works on any type of data, and it is completely random. If
you shuffle the same array twice, you will most likely get different
results each time (there is a statistically insignificant chance that
the computer could produce the same exact set of random
numbers twice in a row, but it’s so small that it’s barely worth
mentioning).
81
“Movies, Comedy, 90s” as listed above, the Tags array would
5.5 Converting Text Into A have three elements:
The array Tags would then contain one element for each piece of
the string that was separated by a comma. If the user entered
82
many ways. It can be used to store lists of data, but the order of
5.6 Using Key/Value Pairs the data is not maintained. Also, instead of using a simple
numeric index to track its position in the list, the Dictionary uses a
To Store Data Key/Value relationship, where both the Key and the Value can be
of any data type. The Dictionary is technically a class, so it must
As discussed above, arrays are useful for storing lists of similar
be instantiated before it can be used (similar to the Date data
items. In addition, they maintain the order of elements until you
type you learned about in Chapter Two).
modify it. But the only way you can look up a value is by using the
index. Some languages have a feature called associative arrays To create a Dictionary, use the Dim keyword, just as with other
that essentially allow you to use any data type as an “index” by data types:
which you can look up a value. So, while a traditional array might
look like this: Dim settings As New Dictionary
Index Value Notice that this example used the shorter method of instantiating
0 Abe your variable by including the New operator on the same line as
1 Mary the Dim keyword.
2 Zeke
Key Value
0 Abe
1 Mary
2 Zeke
Xojo does not have associative arrays, but it does have a data
type called Dictionary that is similar to an associative array in
83
Although it may not be obvious from the example, you have
provided Keys as well. Take this line of code for example:
The Key in this line is “Dark Side” and the Value is a boolean,
which happens to be true in this example. So in essence, you are
storing data very much like an array, but you are manually
assigning the Key rather than using a numeric index.
MsgBox(settings.Lookup("Lightsaber Color","Red"))
Because the “Lightsaber Color” Key does not exist, the message
box in this case will display “Red.” If you use an existing key:
MsgBox(settings.Lookup("Title","Pilot"))
... then you’ll see the Value from the Dictionary as expected.
To check for the existence of a specific Key, use the HasKey To remove an entry from the Dictionary, use the Remove method,
function. HasKey takes the Key you’re looking for as a parameter which takes the Key as its parameter:
and returns a boolean: true if the Key exists and false if it does
not: settings.Remove("Dark Side")
If settings.HasKey("Mentor") Then To remove all entries from the Dictionary at once, use the Clear
! MsgBox("Mentor: " + settings.Value("Mentor"))
method:
Else
! MsgBox("No mentor was found")
End If settings.Clear
85
1) If you haven’t already done so, launch Xojo and create a new
5.7 Hands On With Arrays Web Application. Save it as “ToDoList”.
To start, you’ll build the interface, then add your code later. The following
As mentioned at the beginning of the chapter, your next sample
table lists the types and names of controls you will need. As before, don’t
project is a web-based To Do List Manager. The finished web app worry too much about where each control should be positioned; use the
might look something like this: screenshot at the beginning of the chapter as a guide, but feel free to use
your creativity as well.
Your end user will enter To Do Items into ToDoField, then click AddButton
to add them to ToDoListBox. The data for ToDoListBox will be stored in an
array behind the scenes.
Since the ToDoListBox does not need a column header, you can turn off its
column header by switching the HasHeading property in its Inspector to
OFF.
If you have resized any of your running apps so far in this book, you
probably noticed that the controls haven’t necessarily behaved as
expected; instead of expanding to fill the window, they stay the same size
and the same distance from the top left corner. This can be fixed by
changing the control locking in the Inspector. You can lock any edge of a
86
control; when that edge is locked, it will maintain its distance from that 4) Add a method called “UpdateToDoListBox” to WebPage1.
edge of the window. So a control locked to the left and top will stay in the
same position, while a control locked to the right and top will always be in Whenever a change is made to your array, you’ll need to update the data
the upper right corner of the window. Your to-do app should fill the browser displayed in ToDoListBox. Because you’ll need to do this from several
window, so lock the controls as listed in this table. places in your code, you’ll create a method for it. Choose Method from the
Insert menu. Name the method UpdateToDoListBox.
Control Lock
5) Add this code to the UpdateToDoListBox method:
ToDoField Left, Top, Right
In the last chapter, you learned a bit about scope, or where a variable can toDoList.Append(ToDoField.Text)
be accessed. Because every control on your window will need access to UpdateToDoListBox
your array of To Do Items, you can’t simply declare it in a method. You need ToDoField.Text = ""
to make it a property of the web page. Adding a property to a web page (or
a window in a desktop app) means that it is accessible from any code on This code provides a way for your end user to get data into the array. The
that web page, whether it’s part of a method you create or in a control’s data will come from ToDoField, and ToDoButton will do the work of adding
event. it to the array. It will then run the UpdateToDoListBox method. Finally, it will
clear the contents of ToDoField so that your user doesn’t accidentally add
the same item multiple times. To make data entry more efficient for your
87
end user, you want to set AddButton’s Default property to true; that way, a 9) Add this code to ShuffleButton’s Action event:
user can add an item to the list simply by pressing Enter or Return.
toDoList.Shuffle
As noted above, the first line adds your user’s text to the array. The second UpdateToDoListBox
line updates your display. And the third line clears out any existing text in
ToDoField. If you run the project now, you should be able to add items to
Finally, you want to allow your end users to sort and shuffle their To Do
the list.
Items. The previous two steps provide that functionality.
toDoList.Sort
UpdateToDoListBox
88
11) Quit your application.
89
Chapter 6
May I Take
Your Order?
CONTENTS
1. Chapter Overview
2. Introduction to Events
3. Windows
4. Input
5. Buttons
6. Pickers
91
Events are not limited to controls. Your windows (note: the
6.2 Introduction to interface element, not the operating system!) also have events.
For that matter, your application itself has events!
Events
As mentioned above, an event is something that happens.
Sometimes an event is triggered when the user does something,
like clicking a button or choosing a menu item. Other times, an
event is triggered by the computer or by the app, such as when
an application launches or a window is opened.
Your popup menu also has a Change event that fires when the
user makes a selection. You can use the Change event to
respond to the user’s choice.
92
Once your ListBox is in place, click on the window background, then go to
6.3 Windows the Insert menu and choose Event Handler (it’s important to make sure the
window itself is selected, because Xojo will add the event handler to
whatever control is selected). A list of events will appear. Select the Open
event and press the OK button. You will be taken to Window1’s Open
event.
Don’t add the word “Open” to the ListBox, though; use each event’s name.
6) Click away from your application and back to it. Drag the
window around. Click in the window outside the ListBox.
93
Windows have other events that won’t be covered in this book.
You are encouraged to explore these events on your own. The
ListBox method above is an excellent way to learn what triggers
different events.
Xojo is not the only language that uses events; many other
languages use them as well, such as Java, JavaScript, and C++.
That’s not to say that users with larger displays won’t be able to
resize your window to fit. That’s where two more window
properties come into play: MaxWidth and MaxHeight. These
numbers indicate how large the window is allowed to become.
94
The default value for both properties is 32,000 points, which is so
large that no user is likely to run into that limitation. If you need to
set a smaller maximum size, use these properties to do so.
On the other hand, you may also need to define a minimum size
for your window using the MinWidth and MinHeight properties.
These properties determine how small a user can make the
window. For example, you may have certain interface elements
that require a certain amount of space. Using MinWidth and
MinHeight, you can guarantee that the user will not be able to
resize your window to too small a size.
The maximum and minimum widths and heights assume that your
window’s size is adjustable at all. You can set this using the
Resizable property. If Resizable is true, the user will be able to
shrink or expand your window using the operating system’s
native abilities. If it is false, the user will be unable to do so
(although you may still set the width and height in code when
necessary).
95
Also, all four of these controls have a Name property. Like a
6.4 Input window’s Name property, this is the name by which you will refer
to the control in your code. Again, it is good practice to give your
In earlier chapters, you used a TextField to get information into
controls meaningful names related to their purpose, such as
your application. The TextField is one of several input controls
FirstNameField or UsernameField.
that you may use in your projects, the others being TextArea,
PasswordField, and ComboBox. In this section, you will learn These controls also have some common properties related to
about the events and properties of each of these controls. their contents. One such property is the Text property. The Text
property contains whatever text is contained in the control. So if
you have a TextField called FirstNameField, you can access its
contents by using this code:
firstName = FirstNameField.Text
Sometimes your user will have some of the text selected. The
TextField, TextArea, and PasswordField have a property called
SelText, which will give you only the selected text. If you wanted
to grab the selected text from a TextField called FirstNameField,
you could use the following code:
currentSelection = FirstNameField.SelText
But first, all of these controls have some properties and events in
common. For example, all four input controls have properties to Other times, you may need information about the selected text,
set their size and position: Left, Top, Width, and Height. These are such as its length or position, without needing to know exactly
all measured in pixels. Note that the Left and Top properties are what the selected text is. All four of the input controls have two
relative to the window that’s holding the control and not the properties called SelStart and SelLength. SelStart will give you
screen itself. the position of the first selected character and SelLength will give
you the length of the selection text.
96
The TextField itself is a simple text box that allows the user to called BiographyField, where a user was to enter some
enter plain text. It doesn’t support inline styles like bold or italics background information on himself or herself, and you wanted to
or different fonts. However, you can set the entire TextField to be allow the user to make certain words bold. You could add a
bold or italic or a specific font. Whatever style, font, and text size PushButton to the window with this code in its Action event:
you choose will be applied to the entire TextField.
BiographyField.SelBold = True
Setting SelBold back to False turns off the bold style. Most style
buttons toggle a style on and off, which you could do with this
code:
97
is a TextField with the Password property set to True. It is parameter, followed by a string with the text you’d like to add (as
provided as a separate control for your convenience. with arrays, the rows in a ComboBox are zero-based).
The ComboBox allows the user to choose from several If you should need to clear out all of the rows from a ComboBox,
predetermined options or enter one of his or her own choosing. it also has a method called DeleteAllRows, which does exactly
These predetermined options are set up using the ComboBox’s what its name indicates.
AddRow method. For example, imagine you had a ComboBox for
While it’s not technically an input control, this is a good time to
the user to select his or her grade in school. You could use the
learn about the Label, a control whose function is primarily
ComboBox’s Open event to create a few common options:
decorative. Its purpose is to serve as a label for other controls,
Me.AddRow("6") such as TextFields, TextAreas, and others. Because of this, its
Me.AddRow("7") Caption is also very important. You used labels in the sample
Me.AddRow("8")
project from Chapter Two. In a well designed application, many of
Me.AddRow("9")
Me.AddRow("10") your controls will have corresponding Labels.
Me.AddRow("11")
Me.AddRow("12")
The AddRow method used in the last code example allows you to
add choices to a ComboBox. You will see similar methods in
other controls later in this chapter. AddRow takes a string and
adds a new row to the end of the list of choices in a ComboBox.
If you should need to add a new row in a certain location, you can
use the InsertRow method. InsertRow takes an integer indicating
where in the list you’d like to insert the new row as its first
98
As with the input controls discussed above, these buttons also
6.5 Buttons have properties related to their size and position: Left, Top, Width,
and Height. You will find this to be a common thread among all
In this section, you will learn about different types of buttons. You
controls. Also, each of these buttons has a Name property; again,
may wonder why you would have more than one kind of button,
the button’s Name is how you refer to the button in your code. As
but each serves a slightly different purpose. Choosing the right
with all controls, it is best to give your buttons meaningful names
interface element for the right task is a fundamental part of user
that are related to their purpose, such as CancelButton,
interface design.
SendEmailButton, etc.
Of the many properties that a BevelButton has which a 8) Change your BevelButton’s Caption to “Bold” and set its
PushButton does not, an interesting one is the Value property. Name to “BoldButton”.
Value is a boolean, and when it is set to True, the BevelButton will
9) Add another BevelButton with the Caption “Italic” and the
take on a darker, “pressed” appearance. This makes the Name “ItalicButton”.
BevelButton useful as a toggle.
10) In StyleDemoField’s SelChange event, add the following
1) In your Events project, add a BevelButton to Window1. code
6) Quit your application 12) In ItalicButton’s Action event, add this code:
In your code, you can determine whether a BevelButton is in its StyleDemoField.SelItalic = Me.Value
A common use for a BevelButton that toggles is to set styles for 14) Type some text into your TextArea.
text. You should be able to use your Bold and Italic buttons to modify the style
of your text. In addition, when you click on or select styled text, the Bold
and Italic buttons should toggle to reflect the text that you have selected.
100
15) Quit your application. 16) In your Events project, add a SegmentedControl to your
window.
As you can see from this example, by using the events and
properties of your controls, you can begin to build some If your window is getting too crowded, feel free to delete the controls from
the older examples.
complicated interactions. Based on this example, it wouldn’t take
much more work to add more styles, as well as font choices and By default, your SegmentedControl will have two items: One and Two. You
text sizes. can edit these or add more using the Inspector, but for now, stay with the
default.
The SegmentedControl has an Action event, too, but it has a
17) In the SegmentedControl’s Action event, enter the following
significant difference from that of the PushButton and
code:
BevelButton. The SegmentedControl’s Action event provides you
with a parameter: ItemIndex as Integer. This is because the Dim theChoice As SegmentedControlItem
SegmentedControl is used for making choices, not just a simple theChoice = Me.Items(itemIndex)
MsgBox theChoice.Title
action like the PushButton. More specifically, the
SegmentedControl is intended for situations where the user must
Before you run your project, let’s examine the code. The first line creates a
choose among two or more mutually exclusive choices. One and
variable called theChoice, with a data type of SegmentedControlItem.
only one choice can be made. The ItemIndex provided to you in Remember from above that the SegmentedControl contains an array of
the Action event tells you which choice the user made, as SegmentedControlItems, so you’ll use this variable to store the item that’s
indicated by which Segment of the SegmentedControl the user chosen by the user. That’s what happens in the second line: you use the
ItemIndex parameter provided by the Action event (the ItemIndex indicates
clicked on.
which segment the user chose) to pull the appropriate
SegmentedControlItem from the Items array. Finally, you present the text of
One property of the SegmentedControl is Items, which is an array
the chosen item to the user by displaying its Title property in a message
of choices. Each choice is actually an instance of a class called
box.
SegmentedControlItem. You can then determine which item was
clicked by using the SegmentedControlItem’s Title property. If this 18) Run your project.
sounds confusing, perhaps a code example is in order. 19) Switch back and forth between the segments.
You should see a message box with the item name on each change.
101
20) Quit your application.
102
RadioButtons contains a set of mutually exclusive choices.
6.6 Pickers Selecting one deselects all of the others.
Another category of controls is known as pickers. These controls 1) Create a new Xojo project and save it as “Options”.
are used to allow the end user to set options and make choices.
2) In Window1, add three RadioButtons.
In this section, you will learn about CheckBox, RadioButtons,
For this exercise, It doesn’t matter what you call them or what their
Sliders, UpDownArrows, and PopupMenu. As with the other
captions are.
controls discussed in this chapter, these controls have the usual
group of properties related to size and position: Left, Top, Width, 3) Run your project.
and Height.
4) Notice that when you select one RadioButton, the others are
deselected.
The CheckBox is best used when the end user needs to turn an
option or setting on or off. You’ve most likely encountered these 5) Quit your application.
before in applications or even in web forms. The CheckBox has a
Name property, which is how you refer to the CheckBox in code,
and a Caption property, which is the text label presented to the
user.
103
person ordering could order one meat and one cheese. So how do you determine which RadioButtons are related to each
RadioButtons might be a good way to design this interface. other and which ones are independent? This is done by looking at
the control’s parent.
Go back to your Options project.
10) Delete all of the RadioButtons from Window1
6) Give your three RadioButtons these captions: “Ham”,
“Turkey”, and “Salami”. 11) Add a Canvas to Window1.
7) Add three more RadioButtons with these captions: “Swiss”, The Canvas will be covered in more depth later in this chapter. Make the
“Cheddar”, and “Provolone”. canvas about half the width of the window and almost the full height.
8) Run your project. 12) Add a RadioButton to Window1, but drop it inside the
Canvas.
Do you see the problem? Selecting a sandwich meat deselects all of the
cheese options, and selecting a cheese deselects all of the meat options. In Note that the border of the Canvas will turn red. This indicates that the
a real world example, you may wind up with some frustrated customers. Canvas is now the parent of the RadioButton.
9) Quit your application. 13) Add two more RadioButtons inside the Canvas.
104
This is the numeric value that the Slider will have as a default until property, so if you need such features, you will either need to
the user changes it or until your code changes it. manage them yourself or use a Slider.
1) Create a new Xojo project and save it as “Slider”. UpDownArrows have two important events to note: Up and
Down. The Up event is triggered when the user clicks the upward
2) Add a TextField to Window1.
facing arrow, and the Down event is triggered when the user
3) Add a Slider to Window1. clicks the downward facing arrow.
In the Inspector, set the Slider’s Minimum to 1, its Maximum to 100, and its
1) Create a new Xojo project and save it as “Arrows”.
Value to 50. Set the Slider’s LiveScroll property to True.
105
6) Run your project. indicates which item in the PopupMenu has been chosen (this list
is zero-based).
7) Use the UpDownArrows control to change the value
displayed in the TextField.
But before you will have a ListIndex to work with, you’ll need to
8) Quit your application. add some items to your PopupMenu. This is done using the
AddRow method.
Me.AddRow("PopupMenu")
Me.AddRow("TextArea")
Me.AddRow("UpDownArrows")
Me.AddRow("Window")
Most of the other properties of the PopupMenu that you will use
on a regular basis will be accessed through code. The property
you may use most often is the ListIndex property. The ListIndex
106
5) Run your project. For the record, you can also access the visible text on a
PopupMenu by using its Text property:
6) Choose an item from the menu. You should see a message
box with the item you’ve selected.
myChoice = MyPopupMenu.Text
7) Quit your application.
As you can see in the example above, the AddRow method takes
a string as its parameter. This string is the text that will appear for
that menu item. AddRow will always add a menu item to the end
of the list. If you need to insert a menu item at a specific place,
you can use the InsertRow method. InsertRow takes two
parameters: first, an integer indicating its position in the list
(again, this list is zero-based), and then a string that will appear
for that menu item.
myChoice = MyPopupMenu.List(MyPopupMenu.ListIndex)
107
1) Create a new project in Xojo and save it as “Menu”.
6.7 Hands On With 2) Change Window1’s title to something meaningful, such as
If you want to get creative with the food options, feel free to do so!
10) Add another Label to Window1 and change its Text property
to “Notes:”.
108
11) Add a TextField next to that Label and change its Name to CheeseCheckBox.Value = False
“NotesField”. BaconCheckBox.Value = False
NotesField.Text = ""
12) Add another Label to Window1 and change its Text property
to “Your Order:”. 18) Add a method to Window1 called “CompileOrder”. Its code
13) Add a TextArea near that Label and change its Name to follows:
“OrderArea”.
Dim theOrder As String
14) Add two Buttons near the bottom of Window1. Change their If MainDishMenu.ListIndex <> -1 Then
Names to “ResetButton” and “OrderButton”, and change ! OrderArea.Text = ""
! theOrder = MainDishMenu.Text + EndOfLine
their Captions to “Reset” and “Order”.
! If FriesRadio.Value Then
15) Set OrderButton’s Enabled property to OFF. ! ! theOrder = theOrder + FriesRadio.Caption
! ! theOrder = theOrder + EndOfLine
This will prevent users from placing their orders without choosing a main ! End If
dish. ! If PotatoRadio.Value Then
! ! theOrder = theOrder + PotatoRadio.Caption
16) In MainDishMenu’s Change event, add this code: ! ! theOrder = theOrder + EndOfLine
! End If
If Me.ListIndex = -1 Then ! If OnionRingRadio.Value Then
OrderButton.Enabled = False ! ! theOrder = theOrder ¬
Else ! ! ! + OnionRingRadio.Caption
OrderButton.Enabled = True ! ! theOrder = theOrder + EndOfLine
End If ! End If
! If CheeseCheckBox.Value Then
! ! theOrder = theOrder ¬
17) In ResetButton’s Action event, enter this code to reset all of
! ! ! + CheeseCheckBox.Caption
the controls on the window: ! ! theOrder = theOrder + EndOfLine
! End If
OrderArea.Text = "" ! If BaconCheckBox.Value Then
MainDishMenu.ListIndex = -1 ! ! theOrder = theOrder ¬
FriesRadio.Value = False ! ! ! + BaconCheckBox.Caption
PotatoRadio.Value = False ! ! theOrder = theOrder + EndOfLine
OnionRingRadio.Value = False ! End If
109
! theOrder = theOrder + NotesField.Text
! OrderArea.Text = theOrder
End If
CompileOrder
Obviously, this sample project won’t place any real orders for
actual food. Its goal is to show you a combination of controls
working together in one interface. For extra practice, try refining
the user interface of this project by using GroupBoxes and
SegmentedControls.
110
Chapter 7
Just
Browsing
CONTENTS
1. Chapter Overview
2. ListBox
3. Decor
4. Organizers
5. Indicators
112
7.2 ListBox
One major control that has not yet been covered is the ListBox.
The ListBox is an extremely useful control with many events and
properties. This section will provide an introduction to it.
As with the other controls in this chapter, the ListBox features the
The text that’s contained in the header cells can be changed by
usual set of size and position properties. A quick glance at the
using the Inspector to the set the InitialValue property. Enter your
Inspector, however, reveals many more properties. Two important
headings separated by tabs. If you enter text on a second line,
properties of the ListBox are ColumnCount and HasHeading.
new rows will be added to the ListBox.
ColumnCount is an integer indicating how many columns the
ListBox has. The columns themselves, are in a zero-based list, so The ListBox also has some events and methods that may look
a three column ListBox will have column 0, column 1, and column familiar from other controls. For example, you saw that the
2. HasHeading is a boolean that determines whether the ListBox PopupMenu and the ComboBox both have a method called
will display a header row. A header row is visually different from AddRow. The ListBox has that method as well. As with the other
the other rows, and it also maintains its position at the top of the controls with this event, AddRow takes a string as a parameter.
ListBox while the other rows are scrolled. That string will be added to the end of the ListBox, in the first
column.
113
This may lead you to wonder how you populate the other cells in In addition to the AddRow method, the ListBox also supports the
that row. Here’s an example of the Open event of a three column InsertRow method. As with the PopupMenu and ComboBox,
ListBox: InsertRow takes two parameters: an integer indicating its position
in the list, and a string to add to the ListBox. LastIndex works
Me.AddRow("Dylan")
with InsertRow the same way it works with AddRow, so it is safe
Me.Cell(Me.LastIndex, 1) = "Bob"
Me.Cell(Me.LastIndex, 2) = "Musician" to use no matter how you add data to the ListBox.
When the user selects a row in the ListBox, its Change event is
That code would add one row with three cells. Add a few more
triggered. The Change event doesn’t provide you with the
rows, and it might look something like this:
currently selected row, but as you saw in previous chapters, you
can access this information using the ListBox’s Index property.
Dylan Bob Musician
Index is zero-based, so the first row has an index of zero. If no
Bezos Jeff Businessman
row is currently selected, the Index will be negative one.
Bolt Usain Athlete
114
7.3 Decor
A glance at the Decor section of the controls list in Xojo will reveal
quite a few controls in this category. In this section, you will learn
about the GroupBox and the Canvas.
115
fact, in this section, you will only look at one event in the Canvas: 8) Quit your application.
the Paint event.
9) Change the code in the Paint event to this:
1) Create a new Xojo project and save it as “Canvas”. 10) Run your project.
2) Add a Canvas to Window1. You should see several shapes drawn on the window.
3) Add the following code to Canvas1’s Paint event: 11) Quit your application.
g.DrawString("Hello!", 20, 20) By now, you may be wondering what’s happening. The Graphics
object provided by the Paint event of the Canvas allows you to do
4) Run your project. almost anything, from displaying text to drawing shapes and
pictures. This may not mean much now, but when this book
When Window1 appears, it should say, “Hello!” on it.
discusses graphics, printing, and subclasses, you will see that
5) Quit your application. you can even create your own custom controls with the Canvas.
6) Change the code in the Paint event to this:
116
1) Create a new Xojo project and save it as “Tabs”.
7.4 Organizers 2) Drag a TabPanel onto Window1.
This section will cover the TabPanel and the PagePanel. These 3) In the Inspector, click the Edit button next to Panels under
controls, like the GroupBox, are useful for grouping other controls Appearance.
into logical units. But they offer the advantage of hiding and
4) Change Tab0 to “Global Settings”.
showing these groups of controls as well.
5) Change Tab1 to “User Settings”.
6) Back in the window editor, with the first tab of the TabPanel
highlighted, add some controls of your choosing.
9) Switch back and forth between the tabs and notice how the
controls are swapped out.
If you need to know which tab has been selected, the TabPanel
does provide a Change event. You can find out which tab is
You’ve most likely encountered the TabPanel in various selected by accessing the TabPanel’s TabIndex property.
applications already, especially in their preferences and options
The PagePanel is similar to the TabPanel, except that navigation
windows. The TabPanel, as its name implies, it used to show
is not provided for you. While the TabPanel provides tabs across
certain groups of controls while hiding others. The hidden
the top to allow the end user to switch easily, you must provide
controls remain active and accessible to your code, but they
your own navigation method for the PagePanel. This makes the
become invisible to the end user.
PagePanel very useful for a “wizard” type of interface that walks a
user through several steps in a certain order.
117
Navigation is done by setting the PagePanel’s Value property. The new account, you could set the PagePanel to take them to a
Value property is an integer indicating which page is currently page with a sign up form. If they choose to use outside
active (the list of pages is zero-based). The pages are set up by authentication, the PagePanel can show them a page where they
you when you design the window, in the same way that you set can enter their credentials for that outside service.
up tabs for the TabPanel.
MyPagePanel.Value = MyPagePanel.Value + 1
MyPagePanel.Value = MyPagePanel.Value - 1
118
The ProgressBar should be used when you can quantify the
7.5 Indicators length of time your application will take or the amount of items
that need to be processed. The ProgressBar has a Maximum
One of the most important aspects of a well designed user
property that should be set to that number. In other words, if your
interface is responsiveness. However, sometimes code simply
application needs to process an array of 200 items, you should
takes a while to run. In these cases, it’s best to provide your user
set the ProgressBar’s Maximum to 200. The ProgressBar’s Value,
with feedback to let him or her know what’s going on. Often, if an
on the other hand, should reflect how far along the process is.
application provides no feedback for more than a few seconds or
doesn’t seem to be doing anything, the user will assume that the 1) Create a new Xojo project and save it as “Progress”.
application has frozen or crashed. If your application is
2) Drag a ProgressBar onto Window1.
processing a large data set, it can be very useful to display a
ProgressBar or ProgressWheel. This indicates to the user that the 3) In the Inspector, make sure the ProgressBar’s Maximum is
set to 100 and its Value is set to zero.
application is still working.
4) Drag a Timer onto Window1.
Timers will be covered in depth in a later chapter; for now, just know that a
Timer will perform a given task after a specific amount of time has passed.
ProgressBar1.Value = ProgressBar1.Value + 1
The ProgressBar should begin to “fill up” from left to right, expanding
slightly every second.
Many times, however, you will not know how many items need to 9) Quit your application.
be processed or how long a given task will take. For example, you
Like the ProgressBar, the ProgressWheel is much more valuable
may be waiting for data to arrive from an outside server, and the
when used in conjunction with Timers and Threads.
speed will be dependent on many factors outside of your control.
In these cases, because it does not indicate how much time
remains for a given task, a ProgressWheel is an appropriate way
to tell your user that the application is still working.
120
8) Select MainViewer. In the Inspector, look for the Locking
7.6 More Hands On With section. Make sure the top, bottom, left, and right edges of
the HTMLViewer are locked.
Controls 9) Using the Inspector, make sure that the ProgressBar and the
Label are locked at the bottom and unlocked at the top.
Because you haven’t yet learned about Timers and Threads, there
is another control that you can use quite effectively with the Here is what your interface might look like in the Window Editor:
5) Add an HTMLViewer to Window1. Set its name to 10) In the Default Button’s Action event, add the following code:
“MainViewer”. It should take up most of the space on the
window. MainViewer.LoadURL(AddressField.Text)
121
11) Run your project.
12) Enter “http://wikipedia.org” into the AddressField and press 18) Run your project.
the Go button.
19) As before, enter “http://wikipedia.org” into the AddressField
It may take a few moments, but the Wikipedia website will load into the and press the PushButton.
HTMLViewer. While it loads, however, the user doesn’t know what’s going
on or if the app is doing anything at all. This time, when the page loads, the ProgressWheel will tell you when the
application is working, the ProgressBar will indicate how much of the page
By adding just seven lines of code to this project, you can make it much remains to be loaded, and the StatusLabel will tell you what the application
more responsive and keep the user better informed. is doing.
14) In MainViewer’s DocumentBegin event, add this code: In above example, you implemented several of the HTMLViewer’s
events. The first one was DocumentBegin, which provides you
ProgressWheel1.Visible = True
with a string called URL. This is the address of the page that the
HTMLViewer is loading.
15) In MainViewer’s DocumentProgressChanged event, add this
code:
You also implemented the DocumentProgress event. This event
ProgressBar1.Value = percentageComplete provides you the URL again, as well as an integer called
StatusLabel.Text = "Loading " + URL PercentageComplete. PercentageComplete, as implied by its
name, tells you how much of the page has been loaded. The fact
16) In MainViewer’s TitleChanged event, add this code: that it’s provided as a percentage is very useful, since that
number is then very easy to use with a ProgressBar, which is
Self.Title = newTitle
exactly what you did above. You also updated StatusLabel’s Text
property with a message that the URL was loading.
17) In MainViewer’s DocumentComplete event, add this code:
Another event you implemented was TitleChanged, which
ProgressWheel1.Visible = False
provides with a string called NewTitle. This is the title of the web
ProgressBar1.Value = 0
StatusLabel.Text = ""
122
page that is being loaded. In the example above, you changed
the window’s Title to match. That’s what this line did:
Self.Title = NewTitle
123
Chapter 8
Do It Yourself
CONTENTS
1. Chapter Overview
4. Variants
6. Modules
8.1 Chapter Overview
So far, you have been introduced to data types, variables, events,
controls, arrays, methods, functions, loops, and more. In fact, at
this point, you have enough tools in your toolbox to build a
sophisticated application, as long as you stick to the predefined
data types provided by Xojo. But you will encounter times, and
they will be many, when you need to define your own data types
with unique properties and methods. For this, you use a class. A
class is something that represents a real life object or an abstract
idea. For example, you may have a class that represents a car (a
real life object) or a bank transaction (an abstract idea).
In this chapter, you will learn to create and use your own classes,
and you will also learn about modules, which provide you with a
way to provide global data and methods to the rest of your
application.
125
8.2 Object Oriented
Programming
There are two basic ways to develop software: Procedural
Programming and Object Oriented Programming.
126
You could continue to add properties, such as hair color, eye
8.3 Classes And Objects color, height, weight, and on and on. For now, this list of
properties will be sufficient.
As mentioned above, a class is something that represents a real
life object (something you can touch or point to) or an abstract But property names are subject to the same rules as variable
idea (a concept or “intangible” idea). To illustrate a class that names (no spaces or punctuation except for the underscore), so a
represents a real life object, you will create a class called Student. cleaned up list of properties would look like this:
Before you start writing code, stop and think about the attributes Property Data Type
of a student. Some obvious things that come to mind are a first FirstName String
name, a last name, a middle name, a birthdate, and a grade level.
LastName String
Next, think about the data types that you will need to store this
MiddleName String
information. The first, last, and middle names are all strings. The
Birthdate Date
birthdate is a date. Grade level is an integer (assume that this is a
GradeLevel Integer
secondary or intermediate school without a Kindergarten class).
A real life object’s attributes can be expressed as properties of a An example of a class that represents an abstract idea would be
class. Your student class could have these properties: a course. A course is not a physical object, and you can’t touch it,
but it’s certainly a concept that impacts your life as a student.
Property Data Type Now think about the attributes of a course. A course has a title,
First Name String an instructor, a room or location, and a subject, like math, social
Last Name String studies, science, etc. These can all be stored as string data. So
Middle Name String your course class could have these properties:
Birthdate Date
Property Data Type
Grade Level Integer
Title String
Instructor String
Room String
127
Again, you could continue to add more properties, but this will do
for now.
4) Repeat this process to add your other properties: LastName
Some of the data types you learned about in previous chapters as String, MiddleName as String, BirthDate as Date, and
are examples of classes that Xojo provides for you. Like those GradeLevel as Integer.
data types, classes must be instantiated, or created, using the 5) Go back to the Insert menu and choose Class to add the
New keyword, like so: next class. Name this class “Course”.
2) Go to the Insert menu and choose Class. 8) Create a new method in Window1 called “GenerateCourses”.
The class editor will appear. This is where you will enter a name for your 9) Add this code to GenerateCourses:
class. Call this class “Student”. The other fields (Super and Interfaces) can
be left blank for now (you’ll learn more about these topics in Chapter Dim c As Course
Thirteen). c = New Course
c.Instructor = "Mr. Smith"
3) With your Student class selected in the Navigator, go to the c.Room = "101"
Insert menu and choose Property. c.Subject = "Science"
c.Title = "Biology"
Your property needs a Name and a Type, and you can optionally set a MyCourses.Append(c)
default value and the property’s scope. Name your property FirstName and c = New Course
set its Type to String. The Scope should be set to Public. You can leave c.Instructor = "Mrs. Jones"
Default blank for now. c.Room = "202"
128
c.Subject = "Mathematics" 13) In Window1’s Open event, you’ll need to run both of those
c.Title = "Geometry" methods:
MyCourses.Append(c)
c = New Course GenerateCourses
c.Instructor = "Ms. Jackson" ListCourses
c.Room = "301"
c.Subject = "World Language"
c.Title = "Spanish III" 14) Run your project.
MyCourses.Append(c)
You should see the Courses appear in the ListBox.
This code will create some sample Courses. Typically, this would be done 15) Quit your application.
from a database or other external data source, but for now, you can create
them in code. It might be tempting at this point to think that the ListBox now
contains information about your Courses. In a very limited sense,
Feel free to add more Courses to the list if you’d like. Note that each time
it does, but it only contains the title of each course. Given the title
you use the line “c = New Course”, the old value is discarded and the
variable is created anew. Also note that the properties you added are
only, it would be difficult to look up other information about the
available in Xojo’s dot notation and autocomplete. course, unless you looped through the array looking for a match
or moved the Course data from an array to a dictionary. And even
10) Add a ListBox to Window1 and name it “CourseBox”.
then, you would have to make sure that you have no duplicate
This ListBox will be used to display a list of available courses. course titles.
11) Create another method in Window1 called “ListCourses”. The reason you don’t have all of the information about your
12) Add this code to ListCourses: Courses in the ListBox is because you have only used one of their
properties. To have access to all of the Course information, you
CourseBox.DeleteAllRows need to use an object.
For Each c as Course in MyCourses
CourseBox.AddRow(c.Title) If you think of your class as a blueprint, you can think of an object
Next
as the actual house.
This method will loop through your array of Courses (using a For...Each
loop) and add each title to the ListBox.
129
A class is a description of something, and an object is the thing
itself. Whenever you use the New keyword, you’re creating a new
object in your code. So in the code above, when you created
some sample Courses, each of those was an object. In that
example, you only grabbed the title from each Course object, but
it’s possible to store an object itself in the ListBox. Change the
ListCourses method to this:
CourseBox.DeleteAllRows
For Each c as Course in MyCourses
! CourseBox.AddRow(c.Title)
! CourseBox.CellTag(CourseBox.LastIndex,0) = c
Next
130
3) Run your project.
8.4 Variants You should see a message box that says, “Hello!”. As you can see, for
string data, using a Variant can be just like using other simple data types.
The obvious question raised by the code change is: what is a
CellTag? As you saw earlier, Every ListBox has a two dimensional 4) Quit your application.
array of Cells. It also has a two dimensional array of CellTags. You
5) Change the code in Window1’s Open event to this:
can think of a CellTag as a “secret compartment” where you can
store data. Dim v As Variant
v = 123
While you can only store string data in a Cell, a CellTag stores a MsgBox v
data type called a Variant. A Variant is a flexible data type that can
store a string, an integer, a double, a date, a dictionary, or any This time, instead of storing a string in the Variant, you’ve stored
other data type, even your custom Course objects. So the code an integer. Recall from Chapter Two that you couldn’t present an
above assigns each Course object to a CellTag in the ListBox. integer to the end user in a message box without first converting
Because of the way the code is structured, each Cell in your it using the Str function. When you use a Variant, however, it
ListBox will contain a CellTag with related course data, stored as converts the data for you automatically.
a Variant.
This can be extremely convenient, but it also be dangerous. Take
This raises another question: how do you get data into and out of this example:
a Variant? Assigning data to a Variant is straightforward, and it
Dim first, second, third As Variant
mirrors the way it’s done with other data types.
first = 123
second = "456"
1) Create a new Xojo project and save it as “Variants”.
third = first + second
2) In Window1’s Open event, add this code: MsgBox third
Dim v As Variant What should be displayed in the message box? You could argue
v = "Hello!"
MsgBox v that the message box should display “123456” (if the string
values of the Variants are combined), but you could also make a
131
case for “579” (if the integer values are combined). Change the 7) In the StudentInformation project, add this code to the
code in Window1’s Open event to the code above and try it for DoubleClick event of CourseBox:
yourself. Were you surprised at the result?
Dim c As Course
If Me.ListIndex <> -1 Then
This illustrates that while Variants are certainly powerful and
! If Me.CellTag(Me.ListIndex, 0) IsA Course Then
useful, they should be used with great care and only when ! ! c = Course(Me.CellTag(Me.ListIndex, 0))
necessary. Storing an object in a ListBox’s CellTag is a perfect ! ! MsgBox(c.Instructor)
! End If
example of when it’s necessary to do so. Even so, great care is
End If
still needed.
This code may look very confusing at first, but it’s simple when it’s broken
That care can be exercised by using the Variant’s properties to
down. First you create a variable, C, which you’ll use to access your Course
force your code to treat the data as a certain type.
object. Second, you verify that the user has selected a valid row in the
ListBox by checking the ListIndex.
6) Change the code in Window1’s Open event to this:
The next line uses the IsA function to check if the Variant (the CellTag in
Dim first, second, third As Variant
Column 0 of the selected Row in the ListBox) is actually a Course object.
first = 123
IsA returns a boolean value: true if the Variant is really of that data type and
second = "456"
false if it is not.
third = first.IntegerValue + second.IntegerValue
MsgBox third
Next, the code does a process called casting, which means it’s telling the
computer for certain that the CellTag in question should be treated as a
The IntegerValue property of the Variant forces the computer to treat the Course object, stored in the variable you called c.
data as numeric instead of string. The Variant also has a StringValue
property, as well as BooleanValue, DataValue, and more. After that line, c is a Course object that you can use as you see fit. In
example above, the Course’s Instructor is displayed to the end user in a
Before you can use an object stored in a Variant, you must tell the message box.
computer what type of object it is. Going back to the StudentInformation
example, you must tell the computer that the Variant stored in the CellTag is 8) Run your project.
a Course object. Before doing so, you should make sure that the object is
Try it out for yourself. When you double click on a Course in the ListBox,
indeed a Course.
you should see a message box showing the Instructor’s name.
132
9) Quit your application.
133
to this:
8.5 Methods and c.DisplayCourseInfo
Functions in Classes
5) Run your project.
In Chapter Four, you learned about method and functions. In that
6) Double click on a Course name in the ListBox to display
chapter, you created those methods and functions as part of the
information about that Course in a message box.
window. You can also create method and functions that are part
of your custom classes. 7) Quit your application.
MsgBox(c.Instructor)
134
11) Now add a method to your Student class called 14) Add another ListBox to Window1 called “StudentBox”.
“Constructor”.
15) Add two TextFields called “FirstNameField” and
There are two special names for methods and functions: Constructor and “LastNameField”.
Destructor. If a class has a method called Constructor, that method will run
as soon as the class is instantiated. In this case, as soon as you create a
16) Add a Button called “EnrollButton”.
Student object with the New operator, the Constructor method will be run. Your end user will enter a first name and a last name in the TextFields, then
Destructor is similar, but it runs when the object is destroyed rather than use the PushButton to add that student to the Course selected in the other
when it is created. The Constructor can take parameters. ListBox.
12) Give your Student Constructor two parameters: “fName As 17) Set EnrollButton’s Enabled property to OFF in the Inspector.
String” and “lName as String”.
18) Add this code to CourseBox’s Change event.
Remember that multiple parameters should be separated by commas.
These two parameters will be used to set the FirstName and LastName EnrollButton.Enabled = (Me.ListIndex <> -1)
properties of the Student.
19) Add this code after the line you just entered:
Now you have a way to create Students and a way to add those Students
to a Course. There are two critical pieces remaining: first, a way to see Dim theCourse As Course
which Students are enrolled in a Course, and second, a mechanism for the StudentBox.DeleteAllRows
user to add Students to a Course (the method exists, but it’s not accessible If Me.CellTag(Me.ListIndex, 0) IsA Course Then
to the user). theCourse = Course(Me.CellTag(Me.ListIndex, 0))
For Each s As Student In ¬
! ! theCourse.EnrolledStudents
StudentBox.AddRow ¬
! ! ! (s.LastName + ", " + s.FirstName)
Next
End If
135
This code will display the Students in a Course. It creates a variable to hold 24) Give your Student class a new method called “FullName”. It
the Course object, gets the Course object from the CellTag, and then loops will take no parameters and it will return a string. Its code
through the Course’s Students and lists them in StudentBox. follows:
20) Add this code to the EnrollButton’s Action event: Return Self.LastName + ", " + Self.FirstName
This code enrolls the Student in the Course. It also adds the Student’s
name to StudentBox. Pay special attention to the fourth line, which takes
advantage of the Constructor to create a new Student based on the first
and last names.
136
4) Run your project.
8.6 Modules It should function in an identical way. The key difference, which isn’t
noticeable to the user, is that the list of Courses is now available to your
Right now, your project has an array of available Courses. This
entire application and not just Window1.
array is stored in Window1. There’s nothing wrong with this
approach, but there will be times when it limits what you can do. 5) Quit your application.
For example, if your application’s interface required more 6) Add a new window to your project by choosing Window from
windows, those new windows would not have access to the list of the Insert menu. Leave its default name of Window2.
Courses.
7) Add a ListBox to Window2 named “OtherCourseBox”. Add
Those are the times when it’s appropriate to store information in a this code to its Open event:
In & Out
CONTENTS
1. Chapter Overview
2. Types of Files
5. Opening Files
In this chapter, you will build a styled text editor that opens, edits,
and saves files. Your app will also be able to change the font,
size, style, and color of the text. Your app may look something
like this:
139
these may contain a picture, even the same picture, but your
9.2 Types Of Files computer needs to open and read each one in a different way. So
a file type not only tells the computer what kind of data it will find
Before start writing code, you need a good understanding of what
in the file, but also how to read it.
a file is. In a nutshell, a file is a unique piece of data on your
computer. It can contain data for a picture, a story, a song, a You can help your application to look for certain types of files by
movie, or even a collection of settings. When you download a using a File Type Set. To add a File Type Set to your project,
song from iTunes or Amazon, that’s a file. When you write a report choose File Type Set from the Insert Menu. Give your File Type
in Word and save it for later, that’s a file. Set a meaningful name, such as PictureTypes (or anything else
that describes the files you’re specifying). Click the left-most
button in the File Type Set Editor command bar to drop down a
list of common file types. You can choose something such as
“image/png” to create a File Type for using PNG picture files.
When you select it, it is added to the File Type Set with many of
its properties filled in for you.
You will see how to use a File Type Set to filter for certain file
types in section 9.4.
Almost every file has a type. A file’s type indicates what kind of
data the file contains. For example, a text file contains plain text
data. A JPEG file contains picture data. An MP3 file contains
audio data. File types are fairly specific: instead of a “picture” file
type, there are JPEGs, PNGs, GIFs, BMPs, and others. Each of
140
not the FolderItem exists on disk. This may seem very odd. After
9.3 Working With Files all, how would you have a FolderItem that points to a non-
existent file? The short answer is that it’s actually quite common.
In Xojo, a file is represented by a class called FolderItem. That
In fact, it’s the only way to create a new file or folder that doesn’t
name is understandably confusing, and many people initially
yet exist. This will become clear later in the chapter.
assume that a FolderItem can only represent a folder. But a
FolderItem can indeed represent any file. Think of a FolderItem as
any item that can be contained in a folder, whether it’s a file or
another folder.
141
you can think of Item as an array of FolderItems rather than a
method.
142
9.4 Handling Open/Save
Dialogs
All this talk about FolderItems is great, but you’re probably
wondering by now how to tell Xojo which files you want to work
with. This is best accomplished through the FolderItemDialog
class.
But before you dig into dialogs, it might be good to explain what
a dialog is. In the simplest terms, a dialog is a minimal window
that either retrieves information from the user or provides
information to the user.
143
There are three special versions of the FolderItemDialog class
that you will use: OpenDialog, SaveAsDialog, and
The first thing this code does is create two variables: one for the
SelectFolderDialog. When you want to prompt the user to open a SelectFolderDialog and one for the FolderItem. Since SelectFolderDialog is
file, use OpenDialog. When you want the user to save a file, use a class, it needs to be instantiated with the New operator.
SaveAsDialog. Finally, when you want the user to choose a folder,
ShowModal is a function in all of the folder item dialog classes. It displays a
use SelectFolderDialog.
modal window to the user (a modal window is one that blocks the rest of
your application until it is dismissed by the user, whether by selecting an
(There are also ways for you to open and save specific files
item or canceling the operation; this is in contrast to a standard dialog,
without the user’s help. This will be covered later in this chapter.) which still allows access to some or all of the application). The function will
return Nil if the user pressed the Cancel button, which is how you check to
Let’s begin with the SelectFolderDialog. see if myFolder is Nil before continuing, or it will return a FolderItem
representing the folder that the user selected.
1) Create a new Xojo project and save it as “Dialogs”.
Once the code verifies that the FolderItem is valid, it adds a few rows to
2) Add a Button and a ListBox to Window1.
FileBox to show you some properties of the selected folder. Note the
3) Name the ListBox “FileBox” and set “Select Folder” as the syntax used to show the FolderItem’s Parent’s Name:
Button’s Caption. myFolder.Parent.Name. Because the Parent is itself a FolderItem, you can
access its properties just as you can do with the FolderItem you initially
4) Add this code to the Button’s Action event: selected.
To open a file, use the OpenDialog class. You will add that to your When opening files, you may want to prohibit your user from
Dialogs project next. choosing inappropriate file types. For example, if you are building
an image editor, you probably don’t want the user opening a
8) Add another Button to Window1. Set “Open File” as its
Word document or an XML file. This is where File Type Sets come
Caption. Add this code to its Action event:
into play, using the Filter property of the FolderItemDialog.
Dim myFile As FolderItem
Dim d As OpenDialog 1) Create a new Xojo project and save it as “FileTypes”.
d = New OpenDialog
2) Create a File Type Set called “ImageFiles” (choose File Type
myFile = d.ShowModal
If myFile <> Nil Then Set from the Insert Menu).
FileBox.AddRow("Name: " + myFile.Name)
3) Add these FileTypes to the set: image/jpeg, image/png
FileBox.AddRow("Size: " + ¬
! ! Str(myFile.Length) + " bytes") 4) Add a Button to Window1. Add this code to its Action event:
FileBox.AddRow("Parent: " + myFile.Parent.Name)
FileBox.AddRow("Created on: " ¬ Dim f As FolderItem
! ! + myFile.CreationDate.ShortDate) Dim d As OpenDialog
FileBox.AddRow("Last modified on: " ¬ d = New OpenDialog
! ! + myFile.ModificationDate.ShortDate) d.Filter = ImageFiles.All
End If f = d.ShowModal()
If f <> Nil Then
! MsgBox(f.Name)
9) Run your project.
End If
10) Click the Button, choose a file, and examine the properties
in FileBox. 5) Run your project.
This time, you have added its CreationDate and ModificationDate. Because
6) Click the Button and browse the computer for files to open.
these are both Date objects, you can treat them just like any other date,
Your application should allow you to choose only PNG and JPG files.
145
7) Quit your application.
You can also use a File Type Set to allow the user to choose a file format
when saving a file.
8) Add another Button with this code in the its Action event:
Dim f As FolderItem
Dim d As SaveAsDialog
d = New SaveAsDialog
d.Filter = ImageFiles.All
f = d.ShowModal()
If f <> Nil Then
! MsgBox(f.Name)
End If
10) Click the Button and you should see a SaveAsDialog that
allows you to specify your new file’s data type as PNG and
JPG.
146
1) Create a new Xojo Desktop project and save it as “Streams”.
9.5 Opening Files 2) Add a Button and a TextArea to Window1.
Looking at data about files is one thing, but displaying and Don’t worry too much about their position and size, but make the TextArea
possibly editing the contents of those files is much more as large as you can easily fit on the window.
file streams, work in a very similar way. Once a file has been instantiating a new OpenDialog, and choosing a file. But once the file is
chosen, you’ll see this line:
chosen, BinaryStream is used to extract data from that file in
small chunks, each of which is processed as it is read into the b = BinaryStream.Open(myFile)
application. When all of the data has been read, it is then
presented to the end user. BinaryStream.Open is a shared method. Typically, a class’s methods can
only be run after you’ve created an instance of that class using the New
operator, but a shared method allows you to run that method at any time.
147
This will be explained in greater detail in Chapter Thirteen. For now, just Fortunately, Xojo includes some functions that make it easy for
note the syntax difference.
you to open some common file types.
Once the BinaryStream has been instantiated, it reads the data from myFile
For example, here is how to open a picture file.
and displays it in the TextArea. The BinaryStream’s Read method brings a
portion of the file’s contents into your application. How large that portion
1) Create a new Xojo Desktop project and save it as
needs to be is up to you. The Read method takes an integer telling it how
“OpenPic”.
many bytes to read. In this case, you’ve told it to read everything in one
shot by specifying the Length of the BinaryStream (a BinaryStream’s Length 2) Add a Button and a Canvas to Window1.
is like a FolderItem’s Length).
The Canvas should cover most of the window. The Button will prompt the
4) Run your project. user to select a picture, which will then be displayed in the Canvas.
5) Click the PushButton and open any file. 3) Add this code to the Button’s Action event:
Note what appears in the TextArea. If you’ve chosen a plain text file, you
Dim myPic As Picture
can read its contents. If you’ve chosen anything else, such an MP3 or a
Dim myFile As FolderItem
picture, you will likely not be able to make heads or tails of the data being Dim d As OpenDialog
displayed. d = New OpenDialog
myFile = d.ShowModal
6) Quit your application. If myFile <> Nil Then
myPic = Picture.Open(myFile)
This project illustrates something very important about most of
If myPic <> Nil Then
the files on your computer: they’re not human-readable. A Canvas1.Backdrop = myPic
human-readable file is one that you can make sense of by looking End If
End If
at the raw contents. There are a few exceptions, such as XML
files, HTML files, or other plain text files, but for the most part, the
The Picture class, as you saw with BinaryStream above, has a shared
files on your computer can only be read by an app that is
method called Open, which takes a FolderItem as its parameter. Again,
designed to read that kind of file. because it is a shared method, you may use it at any time; you do not need
to instantiate the object first.
A custom file format is somewhat like a map or key that tells the
computer which data is stored at which place in the file.
148
The code then sets the Backdrop property of the Canvas. The Backdrop is 3) Add this code to the Button’s Action event:
a Picture in the background of the Canvas. The next chapter will cover
graphics, pictures, and the Canvas in greater depth.
Before setting the Backdrop property, however, you must first check to Dim myFile As FolderItem
make sure the Picture isn’t Nil, just as with the FolderItem. Dim d As OpenDialog
Dim t As TextInputStream
4) Run your project. d = New OpenDialog
myFile = d.ShowModal
5) Click the Button and select a picture file from your If myFile <> Nil Then
computer. t = TextInputStream.Open(myFile)
TextArea1.Text = t.ReadAll
If it is a valid picture, the Canvas should display it.
End If
149
8) Run your project. ListBox1.AddRow(t.ReadLine)
ListBox1.AddRow(t.ReadLine)
9) Click the PushButton and select a text file. ListBox1.AddRow(t.ReadLine)
This time, only the first line of the file should be displayed. You may be
wondering at this point why you would ever want to do something like that. Each time you run ReadLine, the app grabs the next line down.
What use is just the first line of a file? It could be used for a number of But that approach has two problems. First, it’s not efficient code
things. One example would be a quick preview of a file’s contents. Or you
at all. Repetitive tasks like these should be done in a loop. That
may want to display each line in a ListBox.
raises the second problem: how do you know how many times to
10) Quit your application. do it?
11) Remove the TextArea from Window1 and add a ListBox. In a nutshell, you keep reading data until you run out of data to
12) In the PushButton’s Action event, change this line: read. That happens when you reach the end of the file, or EOF
(which stands for End Of File). EOF is a boolean: when it’s false,
TextArea1.Text = t.ReadLine
you still have data left to read; when it’s true, no more data
remains. So the solution to this problem is to use a While...Wend
To this:
loop in conjunction with the TextInputStream’s EOF property.
ListBox1.AddRow(t.ReadLine)
16) Change the code in the Button’s Action event to this:
150
Remember from earlier chapters that the Not operator tells your app that
you want to use the opposite of the boolean value that you’re referring to.
In this case, as long as EOF is not True, the loop will continue.
Each line of the text file should be listed as a separate row in the ListBox.
151
1) Create a new Xojo Desktop project and save it as “TextOut”.
9.6 Creating And Saving 2) Add a Button and a TextArea to Window1.
Reading files is all well and good, but you will likely need to create 3) Add the following code to the Button’s Action event:
some as well. In this section, you will learn how to use the
Dim myFile As FolderItem
TextOutputStream, which is, as its name implies, essentially the Dim d As SaveAsDialog
opposite of the TextInputStream. Dim t As TextOutputStream
d = New SaveAsDialog
Recall that the TextInputStream has functions to read all text, myFile = d.ShowModal
If myFile <> Nil Then
read one line of text, and read a certain number of characters.
t = TextOutputStream.Create(myFile)
The TextOutputStream has similar methods for writing text, t.Write(TextArea1.Text)
although there are only two of them: Write and WriteLine. t.Close
End If
The WriteLine method takes one parameter, which is a string. It
writes that string to the selected file and thens adds an EndOfLine The first few lines of this code should look familiar, although this is the first
character (which could be a line feed, carriage return, or a time you’ve seen the SaveAsDialog. The SaveAsDialog is similar to the
OpenDialog, but it allows you to create files rather than open them. So even
combination of them, depending on what kind of computer you’re
though MyFile is not Nil, the file it represents does not yet exist on your
using). If you’d prefer to use a different delimiter, you can set the
computer. The file is written to the disk when the TextOutputStream’s
TextOutputStream’s Delimiter property. Create function is called. Create is a shared method, as you saw in
previous examples.
The Write function also takes one parameter, also a string. It
writes that string to the selected file, but does not add any After the file is created and you have a TextOutputStream to work with, you
can then add data to the file, using the Write method. In this example, you
delimiters or EndOfLine characters.
are adding all of the text in the TextArea to the file at once.
Here’s an example of the Write method in use. The Close method of the TextOutputStream tells your app that you are
done writing data to the file, so it is safe to be used by other applications.
152
4) Run your project.
5) Add some text to the TextArea and then click the Button.
You will be prompted to save your file. Give it a name and save it.
153
9.7 Hands On With Files
This chapter’s sample project is a styled text editor. You will apply
the information you learned about opening and saving files, as
well as use several of the controls you learned about in earlier
chapters.
Styled text is simply text that allows different fonts, sizes, and
styles, such as bold, underline, and italic. This project will use a
format called RTF, or Rich Text Format, to store the style
information. RTF is a cross-platform, standard way to store styled
text, and the RTF data itself can be stored as plain text, so you
can use TextInputStream and TextOutputStream to open and
save not just your files, but any other RTF file you might have on 2) Here are the controls you’ll need on Window1 and the names
your computer. that the sample code will be using:
Here is a sample of what the interface might look like, but feel free to be FontSizeField N/A ComboBox
creative with yours: BoldButton B BevelButton
ItalicButton I BevelButton
UnderlineButton U BevelButton
154
3) With Window1 selected, go to the Insert Button and choose 6) Add this code to ItalicButton’s Action event:
Property to give Window1 a new property: TheFile As
FolderItem. EditingField.SelItalic = Me.Value
Since the text editor will need to remember which file it’s dealing with when
it’s time to save the file, it should be a property of the window and not
7) Add this code to UnderlineButton’s Action event:
something that is created and thrown away in each button’s Action events.
EditingField.SelUnderline = Me.Value
This is an example of scope. As mentioned earlier, scope indicates how
long your variable will last and what else has access to it. If you were to
create MyFile in the OpenButton’s Action event, MyFile would “go out of 8) In the Rectangle’s MouseDown event, add this code:
scope” when the event is complete; later, when the time comes to save the
file, the SaveButton wouldn’t know which file to use without asking the user Return True
again, which would be annoying for the user, not to mention error prone
(users make mistakes, and your code should protect them from doing so as For the ColorButton, a Rectangle is being used. This control wasn’t covered
much as possible). By making MyFile a property of the window, you can in the chapters on controls and events because it doesn’t really do much.
guarantee that it will not go out of scope. For example, it has no Action event. You can, however, use it as a button in
a pinch. Set its FillColor property to black in the Inspector.
4) Set the ButtonType of each BevelButton to Toggles.
The “Return True” line above is, admittedly, somewhat strange at first
To add some visual flair to your text editor, use the Inspector to set each
glance. To make sure that the Rectangle responds to a mouse click, you
BevelButton’s style to match its purpose: set BoldButton to bold,
need to implement both its MouseDown and MouseUp events. MouseUp is
ItalicButton to italic, and UnderlineButton to underlined. This gives your
where the click should happen, because that’s how buttons work: the
users a clear visual indication of each button’s purpose. You have probably
action happens when the button is released. However, a Rectangle’s
encountered a similar interface before in a text editor or word processor.
MouseUp event doesn’t fire unless you have “Return True” in its
MouseDown event.
5) In BoldButton’s Action event, enter this code:
Dim c As Color
SelBold is a boolean indicating whether a TextArea’s selected text is bold or
If SelectColor(c, "Choose a Text Color") Then
not. By setting SelBold to the BevelButton’s Value property (which matches EditingField.SelTextColor = c
its toggle state), you can make sure that the selected text turns bold when Me.FillColor = c
the button is pressed. End If
155
This code will use the SelectColor function to prompt the user to choose a This is a simple line of code that grabs the value in the ComboBox,
color. SelectColor returns True if the user picks a color and False if he or converts to a numeric value, and sets the TextArea’s selected text to that
she does not. If the user chooses a color, this code sets the selected text’s size.
color to the color that the user selected. It also sets the FillColor property of
the Rectangle itself so that it matches the text. If the user cancels, and FontSizeField is a ComboBox. This is so that you can provide some preset
SelectColor returns False, you can safely ignore it. options for your user while still allowing him or her to enter a custom font
size. This, again, is a fairly common way for an application to handle a font
10) Add this code to FontMenu’s Open event size menu. To add values to FontSizeField, click the Pencil icon that
appears when you hover over the control with your mouse. In the dialog
Dim i, myFontCount As Integer that appears, add some values to that you want to see in your menu. You
myFontCount = FontCount - 1 can use whatever values you like here, but some common font sizes are 10,
For i = 0 To myFontCount 11, 12, 14, 18, 24, 36, and 48. And for additional values, your user can
Me.AddRow(Font(i)) always enter a custom size.
Next
The ComboBox does not have an Action or Change event; when the user
makes a selection or changes the value, the TextChanged event is fired.
The FontMenu’s code should look familiar, as you worked with similar code
in earlier chapters. This code simply loops through each installed font and
13) Run your project.
adds its name to the PopupMenu.
You can’t yet open or save documents, but you can test the editor itself.
11) Add this code to the PopupMenu’s Change event: Enter some text into the TextArea and play with the styles, fonts, sizes, and
colors. Now highlight some text whose style you have already changed. Do
If Me.ListIndex <> -1 Then
you see the problem? The TextArea is responding to the style changes, but
EditingField.SelTextFont = Me.Text
the style buttons, font menu, and other controls are not reflecting the style
End If
of the selected text, which they should.
This code sets the selected text’s font to the font chosen by the user, after 14) Quit your application.
making sure the user chose a non-empty row.
15) Add this code to the TextArea’s SelChange event:
12) Add this code to FontSizeField’s TextChanged event:
Dim i, fontListCount As Integer
EditingField.SelTextSize = CDbl(Me.Text) ColorButton.FillColor = Me.SelTextColor
BoldButton.Value = Me.SelBold
ItalicButton.Value = Me.SelItalic
156
UnderlineButton.Value = Me.SelUnderline 18) Quit your application.
FontSizeField.Text = Str(Me.SelTextSize)
fontListCount = FontMenu.ListCount - 1 19) Add this code to OpenButton’s Action event:
For i = 0 To fontListCount
If Me.SelTextFont = FontMenu.List(i) Then Dim myFile As FolderItem
FontMenu.ListIndex = i Dim d As OpenDialog
Exit Dim textData As TextInputStream
End If Dim rtf As StyledText
Next d = New OpenDialog
d.Title = "Select A File"
myFile = d.ShowModal
The SelChange event is fired whenever the user changes his or her
If myFile <> Nil Then
selection, whether by clicking in a word, using the arrow keys to navigate textData = TextInputStream.Open(myFile)
through the text, or highlighting some text. The font menu, font size field, EditingField.StyledText.RTFData ¬
style buttons, and color button should all change to match whatever text is ! ! = textData.ReadAll
highlighted. textData.Close
TheFile = myFile
Most of this code simply works backward from what the various buttons Self.Title = TheFile.Name
and menus do, making sure the buttons and menus match what is End If
selected. Note that changing the text displayed in the FontMenu is more
involved than simply setting its Text property. The Text property can’t be set
This code will prompt the user to select a file and use a TextInputStream to
directly, so you need to set up a loop to walk through each item in the
get its contents. Because the data will be RTF, you’ll need to read the data
menu and check for a match. When you find one, you set the PopupMenu’s
into the RTFData property of the TextArea’s StyledText property rather than
ListIndex and then Exit the loop.
into the Text property directly. This sounds more confusing than it is in
practice.
16) Run your project again.
Aside from the addition of dealing with RTFData, this code should look very
17) Enter some text into the TextArea and play with the styles,
similar to what you’ve already learned in this chapter. One nice interface
fonts, sizes, and colors.
consideration is that this code also sets the Title of the window to the
This time, the menus and buttons should change when you select different Name of the file being edited. It also sets the window’s TheFile property to
text. But you still can’t open or save documents. the selected file.
Note that on OS X, not all fonts have support for bold and italic variations.
A different font (such as Arial) may be necessary to use all the styles.
157
20) Add this code to SaveButton’s Action event: 21) Run your project.
Dim myFile As FolderItem 22) Experiment with opening and saving files and with editing
Dim d As SaveAsDialog the text and style data. If you have access to other RTF files,
Dim textData As TextOutputStream open them as well.
If TheFile = Nil Then
d = New SaveAsDialog 23) Quit your application.
d.Title = "Save Your File"
In this chapter, you have learned the fundamentals of reading and
myFile = d.ShowModal
Else writing data. But there is still much to learn, especially when it
myFile = TheFile comes to pictures and databases, both of which you’ll learn
End If
about in the coming chapters. For now, you should have a solid
If myFile <> Nil Then
textData = TextOutputStream.Create(myFile) handle on reading and writing files, especially text files.
textData.Write(EditingField.StyledText.RTFData)
Self.Title = MyFile.Name
End If
Here in SaveButton’s Action event, things aren’t quite as simple. If the user
has already opened a file, you can save data to the file using the window’s
TheFile property. However, if the user has started from scratch, you’ll need
to ask the user where to save the file and what to call it. Once that part is
done, it’s a matter of writing the RTFData to the file.
Note that when the file is saved, the window’s Title is updated, in case the
user created a new file.
158
Chapter 10
Picture This
(Then Print It
Out!)
CONTENTS
1. Chapter Overview
4. Printing
In Chapter 2, you learned about some of the data types that Xojo
supports, including strings, numeric data types, dates, and
colors. There are primarily two data types that you will use when
dealing with image data. One of these data types is Picture. As
you probably guessed from its name, the Picture class represents
a picture. That picture can be loaded from a file that you already
have or drawn by your code.
The other data type you will learn about is the Graphics class. It
may seem odd to have both a Graphics class and a Picture class,
but the reasons for this will become clear as you read this
chapter. In reality, the Graphics and Picture classes work together
to help you manage image data.
160
methods you saw in the last chapter. It takes a FolderItem as its parameter
10.2 Working With and returns a Picture object, which is assigned to myPic (assuming the
FolderItem is valid and not Nil).
The Picture class, as noted above, holds an image. Rather than 4) Click the PushButton and select a picture file (any common
discuss it in the abstract, let’s dig right in with an example. By the image format will do, such as JPEG, GIF, PNG, or TIFF).
way, if you like the picture used in this example, you can Notice what happens after you open the file: nothing. Nothing has
download it (and lots of other free pictures) here: http:// happened because you haven’t told your code to do anything with the
www.publicdomainpictures.net. picture object yet.
1) Create a new Desktop project in Xojo and save it as 5) Quit your application.
“Pictures”.
6) Add an ImageWell to Window1.
2) Add a Button to Window1. Add this code to its Action event:
The ImageWell is a control that was not covered in earlier chapters, mostly
because it doesn’t do much. Its job is to display a picture. Size the
Dim f As FolderItem
ImageWell so that it covers most of Window1.
Dim d As OpenDialog
Dim myPic As Picture
7) Just above the “End If” line in the PushButton’s Action event,
d = New OpenDialog
f = d.ShowModal()
add this code:
If f <> Nil Then
myPic = Picture.Open(f) ImageWell1.Image = myPic
End If
8) Run your project.
Some of this code should certainly look familiar. The code creates a few
Again, click the PushButton and select a picture file.
variables and then asks the end user to choose a file. One thing that may
be unfamiliar, however, is that one of those variables has the data type of
Picture.
161
9) This time, you should see your selected picture displayed in
the ImageWell, such as in the screenshot below:
162
5) In the Paint event handler for the Canvas, add this code:
10.3 Drawing From Code If MyPic <> Nil Then
Now that you know the basics of opening and displaying a ! g.DrawPicture(MyPic, 10, 10)
End If
picture, it’s time to learn about the Graphics class. While the
Picture class is extremely useful for storing image data, the
This code draws the picture in the Canvas (as long as a picture is available).
Graphics class does most of the “heavy lifting” when it comes to
displaying and manipulating image data. The Graphics class (provide by the g parameter to the Paint event) has
many methods for manipulating image data. In this example, the
1) Create a new Desktop project and call it Pictures-Canvas. DrawPicture method is being used to draw the selected Picture object into
the Canvas (whatever is in the Graphics property of the Canvas will be
2) Add a Button and add a Canvas. Size it so that it covers displayed onscreen). You will learn much more about the DrawPicture
most of the window. method in this section, but for now, you should know that the three
parameters you have given are the picture to draw followed by the X and Y
3) Add a property to the Window: MyPic As Picture.
coordinates indicating where to draw it.
4) Add this code in the Button’s Action event:
6) Run your project.
Dim f As FolderItem
7) Click the Button and select a picture file.
Dim d As OpenDialog
d = New OpenDialog This time, you should see your selected picture displayed in the Canvas,
f = d.ShowModal()
such as in the screenshot below:
If f <> Nil Then
MyPic = Picture.Open(f)
Canvas1.Invalidate
End If
This is almost identical to the code you entered earlier; only a few lines
have changed. Now the picture you selected is assigned to the property
and the Canvas is told to update itself (by calling Invalidate).
163
of the Canvas, while drawing the image at 72,36 would result in
the image being approximately one inch from the left edge of the
Canvas and one half inch from the top. Take a few minutes to
experiment with different values for the X and Y coordinates.
Notice how the position of the image changes.
But don’t limit yourself by thinking that you can only provide
predetermined numbers as the coordinates. After all, they’re just
integers, so you can give DrawPicture any value that you can
calculate. For example, suppose you wanted to center the image
inside the Canvas. If you knew the size of the image and the size
of the Canvas ahead of time, it would be relatively easy to do the
math to center the image. The challenge comes in when you do
not know either size ahead of time. Fortunately, there’s a fairly
Note that the image displayed in the Canvas doesn’t have the special insert simple way to center an image. The X coordinate should be half
border like it did in the ImageWell. This is because a Canvas doesn’t of the width of the Canvas minus half of the width of the Picture.
provide that frame automatically. Also note that while the ImageWell
The Y coordinate should be the same, only using the height
centered the picture for you, the Canvas does not. At this point, you may
wonder why you would bother with a Canvas instead of ImageWell. In
instead of the width. Conveniently, the Canvas and Picture
short, the Canvas gives you far greater control over the display of your classes helpfully provide you with this information with their
image. Height and Width properties.
The above example used the DrawPicture method with three 10) Change the Paint event to calculate the center position for
parameters: the Picture to draw, followed by the X and Y the image. The code now looks like this:
coordinates at which to draw it. The coordinates are relative to
If MyPic <> Nil Then
the top left corner of the Canvas, so drawing the image at 0,0
! Dim x, y As Integer
would result in the image being tight against the upper left corner ! x = g.Width / 2 - MyPic.Width / 2
164
! y = g.Height / 2 - MyPic.Height / 2
! g.DrawPicture(MyPic, x, y)
End If
The above code calculates X and Y. X is half of the width of the Canvas
minus half of the width of the Picture. And Y is half of the height of the
Canvas minus half of the height of the Picture. If that formula is confusing,
this diagram may help:
Remember that the image is centered within the Canvas, not within the
window.
12) Click the Button and select a picture file. Now that you’ve learned more about how to position your images
using the DrawPicture method, you may be wondering if it’s
This time, you should see your selected picture displayed in the Canvas,
possible to crop or scale your images. And it is possible.
but centered within it:
165
In your Pictures-Canvas project, go to the Paint event and change Now add two more parameters, so that your line of code looks
the line of code containing DrawPicture to this: like this:
g.DrawPicture(MyPic, 20, 20, 150, 150) g.DrawPicture(MyPic, 20, 20, 150, 150, 50, 50)
Those two additional parameters are called DestWidth and These next two parameters are called SourceX and SourceY, and
DestHeight, and they determine the width and height of the image they tell DrawPicture where in the original image to start drawing
when it’s displayed. When you run your project, this time, you’ll from. By default, these are both zero, so that DrawPicture starts
see that the image you select does not go beyond 150 points at the upper left hand corner of the image.
wide or 150 points tall (if the image is smaller than 150 points in
With SourceX and SourceY in place, you might see an image
either dimension, you won’t see the difference). In short,
more like this:
DestWidth and DestHeight allow you to crop the image:
166
So far, that’s seven parameters. As mentioned above, demonstrated here. But used in combination, they allow you great
DrawPicture can take up to nine. The final two are called control over how your image is displayed.
SourceWidth and SourceHeight. These allow you to scale the
This is all great if you have some picture handy on your computer
image. Change the DrawPicture line one more time:
already. But you may have to draw your own at some point. The
g.DrawPicture¬ Graphics class has several methods that allow you to create
! (myPic, 20, 20, 150, 150, 50, 50, 100, 100) images. Rather than go through some long-winded explanations
about these methods, let’s dive into some examples.
This time, the image may look something like this:
1) Create new Xojo Desktop project and save it as “Drawing”.
The “g” variable here is the Graphics property of Canvas1. The Paint event
provides that property for you:
Note that the image is zoomed in, because it’s been scaled up.
4) Run your project.
These additional parameters to DrawPicture will almost always be
Canvas1’s Paint event will fire right away, so there’s no need to click any
calculated values rather than hard-coded numbers as has been buttons. You should see a window that looks like this:
167
7) Run your project again
Note that one rectangle is empty while the other is filled. That’s the
difference between the DrawRect method, which only draws the outline of a
rectangle, and the FillRect method, which colors in the rectangle. They both
take the same four parameters: X, Y, Width, and Height. So to draw a
Notice that the ovals are red. This is because you set the ForeColor
square, you would make sure that width and height were the same number.
property of the Graphics class before drawing the ovals. DrawOval and
FillOval, like DrawRect and FillRect, take four parameters: X, Y, Width, and
5) Quit your application.
Height.
6) Add these lines of code to the end of Canvas1’s Paint event:
8) Quit your application.
g.ForeColor = RGB(255, 0, 0)
g.DrawOval(20, 80, 50, 60)
9) Add these lines of code to the end of Canvas1’s Paint event:
g.FillOval(60, 80, 50, 60)
g.ForeColor = RGB(0, 255, 0)
g.PenWidth = 4
g.DrawRect(20, 200, 30, 40)
g.FillRect(60, 200, 30, 40)
168
This time, you have set the ForeColor to green and also made the “pen” 13) Run your application, and you should see a window that
thicker by setting the PenWidth to 4. looks like this:
Notice that the green rectangle outline is thicker. 14) Quit your application.
11) Quit your application. The Graphics class also has several properties related to drawing
strings. For example you can set its bold property to true before
12) Add these lines of code to the end of Canvas1’s Paint event:
calling DrawString in order to draw bold text (but don’t forget to
g.ForeColor = RGB(0, 0, 255) set it back to false when you no longer need your text to be bold).
g.TextSize = 18
The same goes for italic and underline. In addition, you can set
g.DrawString("This is pretty easy!", 200, 100)
the TextFont and TextSize, and as you saw earlier, the ForeColor,
to control the color of the text.
169
Now that you’ve created a masterpiece, you may want to save it. Note: On Windows, make sure you have the Use GDI Plus property (on the
Windows Build Settings) set to ON.
While it might seem strange, there’s no way to save the contents
of a Graphics object. Only a Picture object can be saved to disk. 5) Quit your application.
This is easily dealt with, however, by drawing to a Picture instead
6) Improve the quality for HiDPI (Retina) screens.
of directly to the Canvas.
The above code works fine, but if you have a HiDPI (Retina) screen (and
1) Return to your Drawing project in Xojo and use Save As to have turned Supports Retina / HiDPI to ON) you may notice that the
create a new project called Drawing-Save. drawings look a bit fuzzy. This is because the new Picture object (p) that
you created does not have the correct scale for a HiDPI screen. To instead
2) Add a property to the Window: MyPic As Picture.
get a Picture object with the right scale, call the Window’s
3) Change the code in Canvas1’s Paint event to this: BitMapForCaching method. Change the “New Picture” line to this:
170
to write the picture to a file. Save requires two parameters: the FolderItem
to save the Picture as, and the file format. In this example, you will save the
Picture as a JPEG.
9) Run your project and click the button to save the drawing.
171
1) Create a new Xojo desktop project and save it as “Printing”.
10.4 Printing 2) Add a Button to Window1. Add this code to its Action event:
Now that you know how to handle Pictures and Graphics, you
Dim g As Graphics
know most of what you need to know to print. Printing is done g = OpenPrinterDialog()
with a Graphics object as well, but it’s not part of a Canvas or a If g <> Nil Then
g.DrawString¬
Picture. This Graphics object is returned by the
! ! ("This is my first print job!", 100, 100)
OpenPrinterDialog function. OpenPrinterDialog asks the user to End If
confirm that he or she intends to print, and then gives you a
Graphics object. Whatever you draw onto that Graphics object is As you can see, OpenPrinterDialog gives you a Graphics object to work
sent to the printer. with. You must check to be sure it’s not Nil before trying to draw to the
Graphics object. If the user presses the Cancel button in the print dialog, G
will be Nil, and no drawing or printing should be done.
Once you’ve verified that G is a valid Graphics object, you may use any of
the methods and properties of the Graphics class. The only difference is
whatever you draw will be printed rather than displayed onscreen.
Dim g As Graphics
g = OpenPrinterDialog()
If g <> Nil Then
g.DrawString¬
! ! ("This is my first print job!",100,100)
172
g.NextPage 2) Add a Button to the window. Set its Caption to “Print” and
g.DrawString("This is my second page!",100,100) place this code in its Action event:
g.NextPage
g.DrawString("This is my third page!",100,100) Dim g As Graphics
End If Dim stp As StyledTextPrinter
g = OpenPrinterDialog()
7) Run your project. If g <> Nil Then
stp = EditingField.StyledTextPrinter(g, g.Width)
8) Click the Button again. stp.DrawBlock(0, 0, g.Height)
End If
You should see a three page document. You now know how to print
multipage documents.
The TextField has a function called StyledTextPrinter that returns an
9) Quit your application. instance of the StyledTextPrinter class. The function takes two parameters:
a Graphics object (which the OpenPrinterDialog provided) and the desired
One general rule of printing is this: never assume. You cannot width of the print area. In this example, the print area will be the entire
predict what the user will do, so your code needs to be prepared width of the page, but you could easily reduce that number to print in a
to handle many different situations, such as different page sizes, narrow column, or even in multiple columns.
different margins, and even different page orientations. That’s why The StyledTextPrinter class has a method called DrawBlock, which draws
it’s best not to use hard-coded positions and sizes for the objects its StyledText into the Graphics object that was specified earlier. DrawBlock
you draw, but to use relative values and scale your drawing takes three parameters: the X coordinate, the Y coordinate, and the height
of the block to be printed. Again, in this example, the entire page will be
proportionally.
used if needed.
You may be thinking that printing a lot of styled text in this fashion
3) Run your project.
would be very tedious, and you’d be right. That’s why the
StyledTextPrinter exists. 4) Either add some styled text to EditingField or open up
another RTF document.
1) Open the StyledTextEditor project you created in the
5) Once you have some styled text to work with, click the Print
previous chapter.
button.
173
6) Quit your application.
174
If PotatoRadio.Value Then
10.5 Hands On With g.DrawString(PotatoRadio.Caption,100,40)
End If
For this reason, this code keeps track of the vertical position on the page
by using a variable called yOffSet. If a line needs to be printed, yOffSet will
be increased, and if a line needs to be skipped, yOffSet will be left alone.
This code is very similar to the code that’s in the CompileOrder method.
The only difference is that instead of adding items to the TextArea, it draws
them to the Graphics object. It also toggles Bold to true for the labels and
to False for the actual items.
In this chapter, you learned some valuable skills for dealing with
images and graphics, as well as for printing your user’s data. You
now have another option to offer to your end users as they use
your solutions.
176
Chapter 11
Connections
CONTENTS
1. Chapter Overview
3. Making Connections
4. Web Connections
178
called HyperText Transfer Protocol (also known as HTTP, which is
11.2 Networking 101: why you often see website addresses beginning with “http”). The
documentation for a protocol is typically extremely technical and
Protocols, Ports, and rather difficult for non-engineers to read. This is not to say that
Finally, each device involved in the communication has an There are a few creative ways to “double up” on IP addresses, but the
truth is that we’ll soon be out of numbers. IPv6 solves this problem by
address. Typically, this address can take two forms: the IP
providing 2128 possible unique addresses. That’s two to the one
address and the DNS name. You may have seen an IP address
hundred twenty eighth power, which is known, in mathematical terms,
before (IP stands for Internet Protocol). It’s a set of four numbers,
as an RDN, or Ridiculously Large Number. Formatted as an integer,
each between zero and 255. For example, there’s a good chance
that number is
that the IP address on your home wireless router (if you have one, 340,282,366,920,938,000,000,000,000,000,000,
of course) is similar to 192.168.1.1. 000,000. That’s enough for each person on the planet to have
51,557,934,381,960,373,252,026,455,671 addresses of
Because these numbers can be difficult to remember, DNS names
his or her own.
are often used instead. A DNS name is a series of words (or
syllables) that take the place of an IP address. For example, you
can easily remember “google.com” as a website address, but you
might find yourself doing fewer searches if you had to remember
and type in “72.14.204.102” every time you needed Google. DNS
180
The code tells the Socket which address (“www.google.com”) and which
11.3 Making Connections port (80) to use. It then tells the Socket to connect to that address. Note
that you can also set the Socket’s address and port in the Inspector.
If that all seems overwhelming, take heart. Xojo has a class called
4) Add an event handler to the Socket to handle the Connected
SocketCore that takes care of a lot of these details for you. You
event.
don’t use SocketCore directly, but rather one of its subclasses (a
subclass is a derivative of another class; you’ll learn more about MsgBox("You are connected!")
subclasses in Chapter 13). These subclasses of SocketCore are
generally referred to as Sockets. This event fires when the Socket has successfully connected to the device
at the specified address using the specified port. Add this code to the
In earlier chapters, you learned about using different kinds of event handler.
1) Create a new desktop project in Xojo and save it as So far, so good, but admittedly, that project is far from impressive.
“Sockets”. After all, the whole point of networking is to send information
back and forth between devices. You can have your application
2) Add a Button to Window1. Also add a TCPSocket.
send data and receive data. To send data with a Socket, you use
Notice that the TCPSocket positions itself below the window editor (in the
the Write method.
“Shelf”). This is because it won’t be part of your application’s user interface.
181
! + EndOfLine) to respond to it. More importantly, you don’t know how to tell it to
Me.Write("GET")
do so, unless you’ve decided to use a protocol.
Dim s As String
s = "Sent " + Str(BytesSent)
s = s + " bytes so far..."
s = s + EndOfLine
TextArea1.AppendText(s)
The TextArea should show you that your socket has connected
successfully, and then it should reveal that you have sent three bytes of
data across the network.
Again, this is still less than impressive, but you now know how to
send data via a Socket using the Write method. What would be
even more impressive, however, would of course be getting some
data back. This is where things get decidedly more difficult. And,
perhaps not coincidentally, this is where protocols come into play
as well. As noted above, a protocol is a set of rules for two
devices to communicate over a network, and without a protocol,
such “conversations” are difficult at best and impossible at worst.
The TCPSocket you have been working with so far has been
operating in something of a vacuum. Without an established
protocol, it doesn’t know how to talk to the other device, or how
182
4) Add a TextField, a Button, and a TextArea to Window1.
11.4 Web Connections 5) Change the PushButton’s caption to “Go” and size the
TextArea so that it takes up most of Window1.
As mentioned earlier, Xojo comes with built-in support for some
common networking protocols, among them the HyperText As far as the exact arrangement, your interface might look something like
Transfer Protocol, or HTTP. The HTTPSocket already knows and this, but feel free to use your own creativity:
As before, notice that the TCPSocket positions itself below the window
editor (in the Shelf). This is because it won’t be part of your application’s
user interface.
183
7) Enter this code into MyWebSocket’s Error event: that’s the code that comes up when the network can’t find the address you
specified.
TextArea1.Text = "Error: " + Str(Code)
For a valid page, notice that you’re not seeing a normal, rendered web
page. What you’re seeing in the TextArea is the HTML source code of a
In the case of an error, the HTTPSocket’s Error event will fire. The Error
page, just like you would see if you chose to View Source in your web
event provides you with the error code, an integer.
browser. If you wanted to see the web page as you normally would, use the
HTMLViewer control that you saw in an earlier chapter.
Of course, the preferable outcome is the successful retrieval of the page
contents. This happens in the PageReceived event. The PageReceived
11) Quit your application.
event provides you with four variables: URL, a string indicating the address
of the page; HTTPStatus, an integer indicating the status of the
transmission; Headers, an instance of the InternetHeaders class, which
gives you additional details about the page; and Content, a string which is
the actual content of the page in question.
TextArea1.Text = Content
That code will simply fill up TextArea1 with the contents of the page.
The page’s contents (as HTML text) should be displayed in the TextArea. If
not, you should see an error code. As noted above, the error code is an
integer. The list of error codes and what they mean can be found in the
Language Reference. To see an example, enter “microsoft.apple.google”
into the TextField and click the PushButton. You will likely see an “Error:
103” message in the TextArea. 103 is the code for a name resolution error;
184
(Post Office Protocol) and IMAP (Internet Message Access
11.5 Hands On With Protocol). Because receiving email messages is decidedly more
complicated than sending them, this project will focus on sending
Sending Email messages. On the surface, it may seem silly to create an
application that can send emails without receiving them, but it’s
actually quite common. Many applications have built-in support
for sending bug reports to the developer; this is often done by
sending an email behind the scenes. In addition, many
applications have a “Share” option that often includes emailing a
link to your friends.
7) Create a new method called “SendTheMessage”. 8) Add this code to MailSocket’s MailSent event:
Dim m As EmailMessage
m = New EmailMessage MsgBox("All mail has been sent!")
m.AddRecipient(ToField.Text)
m.Subject = SubjectField.Text
9) Add this code to MailSocket’s ServerError event:
m.BodyPlainText = MessageArea.Text
m.FromAddress = [ENTER YOUR EMAIL ADDRESS HERE]
MsgBox(ErrorMessage)
MailSocket.Messages.Append(m)
MailSocket.SendMail
Using the MailSent event will help you to keep your end user informed of
the app’s status instead of wondering if anything has happened. Another
This method will gather the information from your interface and put it into
an EmailMessage object, which will then be handed over to MailSocket for
186
important event is the ServerError event. In case something goes wrong, MailSocket.Password = [YOUR ICLOUD PASSWORD]
your user will want to know that, too. MailSocket.Port = 587
MailSocket.ConnectionType = SMTPSecureSocket.TLSv1
Now comes the tricky part. As mentioned earlier, this project requires you MailSocket.Secure = True
to have an email account through Gmail, iCloud, or Yahoo. However, each MailSocket.Connect
of these email systems uses a slightly different method of connecting and SendTheMessage
authenticating, so the code in the PushButton’s Action event will be
different for each. Note that your user name should be your full email address, including the @
sign. Skip to Step 14.
10) If you are using Gmail, proceed to Step 10. For iCloud, go to
Step 12. For Yahoo! Mail, go to Step 13. 13) Yahoo! Mail - Enter this code into the PushButton’s Action
event:
11) Gmail - Enter this code into the PushButton’s Action event:
MailSocket.Address = "smtp.mail.yahoo.com"
MailSocket.Address = "smtp.gmail.com" MailSocket.Username = [YOUR YAHOO USER NAME]
MailSocket.Username ¬ MailSocket.Password = [YOUR YAHOO PASSWORD]
! = [YOUR GMAIL ADDRESS, INCLUDING @] MailSocket.Port = 465
MailSocket.Password = [YOUR GMAIL PASSWORD] MailSocket.Secure = True
MailSocket.Port = 465 MailSocket.Connect
MailSocket.ConnectionType = SMTPSecureSocket.TLSv1 SendTheMessage
MailSocket.SMTPConnectionMode = ¬
! SMTPSecureSocket.ModeSSLTLS
Note that your user name should be just the portion of your email address
MailSocket.Secure = True
that comes before the @ sign.
MailSocket.Connect
SendTheMessage
14) Run your project.
Note that your user name should be your full email address, including the @ 15) Enter an email address, a subject, and a message.
sign. Skip to Step 14.
16) Click the Button to send your message.
12) iCloud - Enter this code into the PushButton’s Action event: Did you see a success message or an error?
187
In all the above code listings, your username and password
should be surrounded by quotation marks, since they are strings.
Also, please note that including passwords and usernames in
your source code is usually frowned upon as a bad practice. It
doesn’t matter much for the purposes of this project, but an
interesting extension to this project would be adding additional
fields to your interface for your username and password so that
they’re not stored as part of your source code.
188
11.6 A Few Closing Notes
About Protocols
Protocols basically come in two forms: existing, established
protocols, and protocols that you create on your own. An existing
protocol could be something like HyperText Transfer Protocol,
used to send data for web browsing, or the protocols used for
email messaging: Post Office Protocol and Simple Mail Transfer
Protocol. These established protocols are usually accepted by
technology industry groups.
This doesn’t mean that you can’t create your own protocols,
however. But be warned that taking on such a task is, to put it
bluntly, a huge undertaking. Admittedly, even using Xojo’ Sockets
to implement an existing protocol is quite difficult.
But Xojo does offer you something to make creating your own
protocol quite a bit easier, as long as the only devices using the
protocol will be other computers running applications built with
Xojo.
189
Chapter 12
Rows &
Columns
CONTENTS
1. Chapter Overview
2. Introduction to Databases
191
Hopefully you can see that most data types match up almost
12.2 Introduction to exactly. Only the textual data types have different names
(although some databases support many more data types, these
Databases are all you need to worry about until you get into very advanced
database work).
For now, you need to understand four key concepts about
databases: tables, columns, rows, and queries. With these data types in mind, you could have a database table
that looked something like this:
A database table is somewhat analogous to a class in Xojo (or
any other programming language). Just like a class, it represents
Column Name Data Type
a real world object (such as a person) or an abstract concept
id INTEGER
(such as a hotel room reservation).
last_name VARCHAR
If you remember back to Chapter 8, you may recall that classes first_name VARCHAR
can have properties, and that each property has a certain data nickname VARCHAR
type. A database table is very similar, except that these properties birthdate DATE
are called columns instead of properties. Each column in a table
represents some attribute of that object or concepts that it
represents. For example, a database table called “people” might Notice that the sample column names listed above use underscores.
have columns for things like the person’s first and last name, the Just like variables in Xojo and all other programming languages,
database column names may not contain spaces. While most
person’s phone number, or the person’s title. As with the
databases support upper and lower case letters in column names, it’s
properties of a class, the columns in a database table must also
common practice in database development to use underscores to
conform to a certain data type. Some common data types are
separate words in a column name. You are more likely to see mixed-
listed below, along with their equivalent in Xojo.
case column names in databases such as SQLite.
VARCHAR String You may also recall that a class is really a blueprint, and not really
INTEGER Integer the concept that it represents. In your code, you work with
192
instances of the class, sometimes called objects, created with the
New operator. A database, again, is very similar. The table is the
blueprint, and each instance of what it represents is called a row.
A row in our people table might look like this:
193
These four verbs describe their own functions. SELECT is used to
12.3 Introduction to get data from the database. INSERT is used to add data to the
database. UPDATE is used to modify existing data in the
Database Queries database. And DELETE is used to remove data from the
database. These four verbs work on columns and rows. There are
But, as mentioned above, there are four concepts you need to
a few other verbs for working with tables: CREATE is used to add
know for now, not just three. The fourth is the query. A query is a
a table, ALTER is used to modify a table, and DROP is used to
way of communicating with the database. This is done with
delete a table.
something called Structured Query Language, or SQL. Almost
every database system in existence speaks SQL or some variant To put several of these pieces together, here is some SQL code to
of it. Many database systems have slightly customized versions create our people table:
of SQL, but the basics are the same.
CREATE TABLE people (
id INTEGER NOT NULL UNIQUE,
SQL is not the only game in town when it comes to databases. There last_name VARCHAR NOT NULL,
are a number of SQL alternatives such as Cassandra, MongoDB, first_name VARCHAR NOT NULL,
CouchDB, and Memcached. While some of these databases are very
nickname VARCHAR,
birthdate DATE,
fast and are designed to operate on a massive scale, it’s not very
PRIMARY KEY(id));
common to find them in use in desktop applications, mobile apps, or
websites smaller than Facebook and Google.
The CREATE TABLE part is self-explanatory: it creates a table in
the database. The next word, “people”, is the name of the table to
Every good language has verbs and SQL is no exception. SQL be created. Inside the parentheses is a list of column names and
has four main verbs that you need to know: SELECT, INSERT, their respective data types, along with some optional information
UPDATE, and DELETE. If you’re wondering why the words are about each column. For example, you can see that the
capitalized, it’s because it’s common convention to use all capital “last_name” column will be VARCHAR (or text), but what does
letters for SQL commands. Lower case works fine, too, but as that NOT NULL following it mean?
you begin to mix SQL queries in with your Xojo code, the upper
case words are easier to pick out.
194
That’s an example of a constraint. NOT NULL means that the The last line, “PRIMARY KEY(id)”, is similar to the NOT NULL
column has to have data in it, even if it’s just an empty string. In UNIQUE constraint on the “id” column. PRIMARY KEY tells the
databases, NULL is equivalent to nothingness, so even an empty database that it should make sure that “id” exists, is unique, and
string is NOT NULL. NULL means that the value doesn’t exist in can always be guaranteed to refer to its row. That is also a
any way whatsoever. To clarify, if someone asked you a question constraint, but it’s a table constraint rather than a column
and you had no answer, that would be similar to NULL, or constraint.
nothingness. On the other hand, if you had an answer, but opted
All of these constraints may lead you to wonder why to bother
not to state it, that’s more like an empty string (NOT NULL).
with them. After all, you could write your code in such a way as to
Another constraint listed above is on the “id” column: UNIQUE. make sure that a certain value always exists or that it never
This means that each row in the table must have a value that no conflicts with another value. But the beauty of constraints is that
other row has. It has to be, in other words, unique. Using an “id” they make the database do that work for you. With a one time
column in this way is very common in database design, as it gives setup, you can now trust that the database will raise an error
you a unique identifier for each row, which makes it easier to when something goes wrong, rather than relying on yourself to
select, update, and delete specific data later on. remember every detail later on.
195
Obviously, [table_name] should be replaced by the actual name of This raises an interesting question: what happens if your text data
the table into which you’re inserting data. Also, each of the has a single quote in it already? If you recall what you learned
columns listed should be an actual column name. The values about string variables in earlier chapters, you can escape a
listed in the second set of parentheses each correspond to a double quote in Xojo by using two double quotes in a row. The
column in the first set of parentheses, so in the example above, same goes for single quotes in SQL (note the two single quotes in
they match up like this: the last name):
column3 value3
After running those two INSERT commands, our “people” table
columnN valueN
would look like this:
You may specify any number of columns in your INSERT, as long id last_name first_name nickname birth_date
as each one has a matching value. 1 Hewson Paul Bono 1960-05-10
196
last_name first_name That would return only the first row, because that is the only row
Hewson Paul in which the last_name column equals ‘Hewson’.
O’Henry Thomas
The WHERE clause can also be used with ranges of data:
Note that the database only returns the columns you specify, in SELECT last_name, first_name, birthdate FROM people
the order you specify. The order of the rows, however, is not WHERE birthdate > ‘1900-01-01’
specified, unless you use the ORDER BY clause: AND birthdate < ‘2012-01-01’
SELECT last_name, first_name FROM people You can also search for a partial match on a string, using the %
ORDER BY last_name, first_name
symbol (sometimes called a wildcard since it matches any text)
and the LIKE operator:
In this particular example, the data set would look the same, but
the order of the rows would be guaranteed. SELECT last_name, first_name FROM people
WHERE last_name LIKE ‘%nr%’
You will sometimes see SQL queries that begin with SELECT *, such
That would return Thomas O’Henry’s record.
as “SELECT * FROM PEOPLE”. The * tells the database that you
want every single column in the table. This is useful for debugging, but
it’s not recommended for production code for two reasons. First, you The wildcard symbol, or %, matches text of any length (including zero
can no longer be sure of the order of the columns you get back from characters), so a search for records that match ‘B%’ would find any
the database. Second, you may be retrieving more data (sometimes far records that begin with an uppercase B. A search for records that
more data) from the database than you need, thereby slowing down match ‘%b’ would find any records that end with a lowercase b. A
your application and using unnecessary disk or network resources. search for records that match ‘%b%’ would find any records that
contain a lowercase b anywhere.
You may also search for particular rows using the WHERE clause:
Another thing to be aware of when doing SELECTs is that almost
SELECT last_name, first_name FROM people every SQL database is case-sensitive, so it treats ‘Hewson’
WHERE last_name = ‘Hewson’ differently from the way it treats ‘hewson’ and the way it treats
197
‘HEWSON’. Each is a different string as far as the database is You can update multiple columns as well:
concerned. To force a case-insensitive search, most databases
UPDATE people SET nickname = ‘Tommy’,
support the LOWER function, which forces everything to
birthdate = ‘1980-10-01’
lowercase: WHERE id = 2
198
That would delete Thomas O’Henry’s record. To clear out all rows:
199
Typically, multiple people can access the database server
12.4 Creating and simultaneously. Some common database servers you might
encounter include Microsoft SQL Server, Oracle, and open source
Connecting to a Local databases like MySQL and PostgreSQL. These types of
But a local database just needs a file. Over the next few sections,
you’ll learn how to create a local database, how to connect to it,
and how to extract data from it. In the process, you’ll build this
chapter’s sample project, a simple email address book.
A remote database, or database server, is a different beast.
Create a new Xojo project and save it as “AddressBook”. The
Although you interact with it the same way, a remote database is
following flowchart explains how the application will work:
running on a database server, usually on a different computer.
200
2) Create a new method in Window1 called “CreateSchema”.
Yes No This method will have the job of creating our database table. To do this, you
will create a string containing the SQL commands to create the table (as
you saw above) and pass this string to a method of the database called
SQLExecute, which, as its name implies, executes a SQL command on the
Create Database database. After running SQLExecute, you’ll run another database method
called Commit. Commit basically tells the database that you’re sure you
want to carry though the command you issued (if you’re ever unsure,
Open Database there’s a method called Rollback that does the opposite).
MyDBFile ¬
201
! = SpecialFolder.ApplicationData.Child("Ch12") Else
If MyDBFile <> Nil Then Return CreateDatabase
MyDatabase = New SQLiteDatabase End If
MyDatabase.DatabaseFile = MyDBFile
If MyDatabase.CreateDatabaseFile Then
This method, which returns a Boolean, will attempt to open the database
If MyDatabase.Connect Then
file. If it succeeds, the app continues as normal. If not, it runs the
CreateSchema
Return True CreateDatabase method and returns its boolean result.
Else
Return False 5) To start this process, add this code to Window1’s Open
End If event:
Else
Return False If Not OpenDatabase Then
End If MsgBox("Unable to open or create database.")
End If Quit
Else
Populate //You’ll create this method ¬
This method will return True if it successfully creates the database, and ! ! in the next section
False if not. This method works by assigning a FolderItem to the database’s End If
DatabaseFile property, then running a database method called
CreateDatabaseFile. It then checks the validity of the database by trying the
Connect function, which returns True if the database is valid and False if
not. If the database is valid, the method then runs the CreateSchema
method. If not, the whole method returns False.
MyDBFile ¬
! = SpecialFolder.ApplicationData.Child("Ch12")
If MyDBFile.Exists Then
MyDatabase = New SQLiteDatabase
MyDatabase.DatabaseFile = MyDBFile
If MyDatabase.Connect() Then
Return True
End If
202
12.5 Accessing The Xojo
Database
Now that your database file is setup and your schema is in place,
you need to learn how to read information from the database and
insert information into the database using Xojo. In Window1’s
Open event, the code above refers to a method you haven’t yet
created, called Populate. It will be the job of the Populate method
to talk to the database and retrieve any data it can find, then
place that data into a ListBox. So, before continuing, you need to
add a ListBox to Window1. You’ll also need a few other controls,
and while you’re adding the ListBox, it’s a good time to lay out
the rest of the sample project. Use your own creativity to design Here is a list of the controls you’ll need, as well as the names you
your interface. It might look something like the one below: should give them:
Control Name
ListBox AddressBox
TextField SearchField
TextField NameField
TextField EmailField
PushButton AddButton
Label SearchLabel
203
You’re almost ready for the Populate method. One thing you need Note that you’re not seeing regular quotation marks embedded in
first, however, is a small function called SQLify. If you recall from the text: those are two single quotes side by side. It can be
earlier in the chapter, SQL uses the single quote as a text difficult to see in certain fonts.
delimiter, meaning any time you have a single in your data, things
Now that SQLify is in place, you’re ready for the Populate
can go terribly wrong. That’s why you need to “escape” every
method. The Populate method will call upon your existing
single quote by doubling it. You could do that manually every time
knowledge of the ListBox (specifically the DeleteAllRows and
you talk to the database by using Xojo’s ReplaceAll function, but
AddRow methods) and will introduce the RecordSet class. A
you’d end up typing a lot of the same code over and over, which
RecordSet is a batch of data returned by a database query (using
violates one of the laws of programming: Don’t Repeat Yourself.
the Database class’s SQLSelect function). A RecordSet can
Instead, create a method in Window1 called “SQLify”. It will take
contain multiple rows. Each row is dealt with one at a time. You
one parameter, Source as String, and it will return a String. Its
navigate through the rows using the RecordSet’s MoveNext
code is very simple, using Xojo’s ReplaceAll function to find any
method. Similar to the TextInputStream you saw in an earlier
single quote and replace it with two single quotes:
chapter, the RecordSet uses EOF (End Of File) when the last row
Dim result As String is reached. Each row within the RecordSet can contain multiple
result = ReplaceAll(Source,"'","''") columns, which you can retrieve by name using the RecordSet’s
Return result
Field method. In that method, you use the same column name
that is specified in the database schema.
So if you ran this code, for example:
Once the RecordSet is retrieved, the Populate method will create
MsgBox SQLify("If it ain't broke, don't fix it!") a new row in the ListBox for each row in the RecordSet, filling in
its data as it goes. But before adding new rows, all existing rows
You would see a message box with this text: will be deleted. If you were to skip this step, your ListBox would
display duplicate data, and would continue to add more
If it ain''t broke, don''t fix it!
duplicates each time it’s populated.
If you find that you’re not a fan of putting all of those SQL queries
together, you can also use Xojo’s Database API to insert the
record without using SQL. This code is an alternate to the code
above (don’t run them both!).
Finally, you need to make sure that the Populate method is run
every time your end user enters text into SearchField. This is
easily accomplished by adding this line of code to SearchField’s
TextChange event:
Populate
206
12.6 More About
Databases
In this chapter, you have learned a great deal about databases,
and how to interact with them using Xojo. Although you have
encountered a lot of information, you have only begun to scratch
the surface of databases. Since databases are often an integral
part of modern applications, you are highly encouraged to learn
more about database theory and more about SQL. If you are
inclined to do so, you can learn more about SQL by visiting http://
www.sqlcourse.com.
207
Chapter 13
All In The
Family:
Subclasses
CONTENTS
1. Chapter Overview
209
Here’s another way to look at it:
13.2 Classes and
TEACHER STUDENT
Subclasses
Think back to the Student class that you created in Chapter 8. FirstName
You gave it the following properties: SubjectArea LastName GradeLevel
MiddleName
BirthDate
Property Data Type
FirstName String
LastName String
MiddleName String
Birthdate Date As you can see, some of the properties are the same. In fact, in
GradeLevel String this example, most of them are.
These properties are certainly relevant to a student, but some This is because a student and a teacher are both people, and
could easily apply to other things, even things that may need to most people have some attributes in common with one another.
be represented in your application, like teachers. In fact, a So what this situation calls for is a new class called Person. The
Teacher class might have these properties: Person class will have the common properties we saw above:
SubjectArea String
But you still need a way to store information and behaviors for
students and teachers. This is where subclasses come into play.
210
A subclass is a class that derives properties and behaviors from
another class, called a superclass. This is similar to the parent/
child relationship described above.
211
4) Give the Person class another method called “SetName”. End If
FirstName = fName
The job of this method is to determine whether the active Person object is a
LastName = lName
Student or a Teacher, and then display the results in a message box. To
determine this information, you will use IsA, an operator built into Xojo that
This method takes two parameters: FName as String and LName as String.
will tell you whether one object is also another kind of object. In this
It allows you to set both the FirstName and LastName properties with one
example, you’ll use it to see if the active Person object is also a Student or
line of code.
a Teacher.
5) Create another new class, this one called “Student”. 10) Lay out your application’s interface.
When you create the class, set its Super property to Person. You may do
Again, it may look something like this, but feel free to use your own
this by typing “Person” into the Super field or by clicking the “edit” button
creativity when designing yours:
and scrolling through the list provided. Student is now a subclass of
Person. Because Student is a subclass of Person, it automatically inherits
the properties and methods of Person. So Student has properties for
FirstName, LastName, MiddleName, and BirthDate, and it has the methods
AnnounceName and SetName. Note that even though it has these
methods, they do not display within the Student class.
212
11) Add these controls to the window. ! ! (FirstNameField.Text, LastNameField.Text)
PeopleList.AddRow(newName)
Control Name PeopleList.CellTag(PeopleList.LastIndex, 0) = t
End If
TextField (w/Label) FirstNameField
FirstNameField.Text = ""
TextField (w/Label) LastNameField LastNameField.Text = ""
PopupMenu (w/Label) TypeMenu FirstNameField.SetFocus
PushButton AddButton
This code will need to create a new Person object (by creating either a
ListBox PeopleList
Student or Teacher object) and then add that Person’s name to the ListBox.
It will also place the newly created object itself in one of the ListBox’s
12) To populate TypeMenu with a list of options, add this code to CellTags. Before you create the object, you’ll need to know whether to
its Open event: instantiate a Teacher or a Student, so you’ll need to check what TypeMenu
says. Finally, in a bit of cleanup, FirstNameField and LastNameField should
Me.AddRow( "Student" ) be cleared and the focus should be set to FirstNameField.
Me.AddRow( "Teacher" )
Me.ListIndex = 0 14) Add this code to PeopleList’s DoubleClick event:
Your students and teachers should show up in the ListBox. Double click on
a few entries and see if they report their types correctly.
214
that some web browsers use to indicate links (this would be a
13.3 Hands On With very good visual indicator for your users that the item is
clickable).
Subclasses
The steps outlined above would work well, but what if you
Speaking of not repeating oneself, subclassing is also a useful needed the same functionality from a Label in a different
way to create custom controls, or controls that exhibit specific Window? You would need to repeat all of the same steps above,
behavior. possibly only changing the URL to be visited.
For example, consider the Label control. As it stands, it’s handy That’s a lot of duplicate effort, which means a lot of wasted time
for indicating the purpose of a neighboring control, such as a and increases the possibility of bugs. This is a perfect situation
TextField or PopupMenu, but it doesn’t really do anything for subclassing.
interesting, at least by default. Suppose you wanted your end
user to be able to click on a label to see more information about Create a new Xojo desktop project and save it as
something, or to visit a URL that you could specify in your code. “CustomControl”.
It would be a relatively simple exercise to implement this
1) Drag the Label from the Library on the right side of the
behavior. screen to the Navigator on the left side of the screen.
In broad strokes, you would need to add a Label to a Window. A subclass with the name CustomLabel will automatically be created.
You would need to implement its MouseDown event; remember Rename it “HyperLabel”, since you’ll be using it for hyperlinks.
215
This makes the text blue and underlined, to make HyperLabel appear more
like a hyperlink on a web page.
Return True
ShowURL(URL)
Self.Underline = True This code “resets” its appearance when the user stops pointing to it.
Self.TextColor = RGB(0, 0, 255)
216
9) Drag HyperLabel onto Window1. Position it anywhere you
like.
10) In the Inspector, set its text to “Xojo” and set its URL
property to “http://www.xojo.com”.
12) Mouse over the HyperLabel and make sure your cursor
changes and the text color changes. Try clicking the text.
217
Chapter 14
CONTENTS
1. Chapter Overview
5. Managing Windows
But another important topic, and one that too many developers
ignore, is the user experience. Some people hear this, and they
try to think of ways to add some magical “wow” factor to their
applications that will grab their users’ attention and set their
applications apart from the crowd.
In reality, the “wow” factor isn’t the important thing. The important
thing is providing your users with a consistent and intuitive
experience.
In this chapter, you will learn skills that you can apply to all three
of these areas.
219
Here is an example of an interface designed without consulting
14.2 User Interface any User Interface Guidelines:
Guidelines
Whether you develop for OS X, Windows, Linux, iOS, Android, the
web, or almost any other common operating system or platform,
there are certain guidelines for the appearance and behavior of
your application. These guidelines are typically authored and
maintained by the companies that produce the operating systems
in question. For example, Google maintains the Android User
Interface Guidelines, while Microsoft takes care of the Windows
User Experience Interaction Guidelines.
Note the inconsistent spacing, incorrect spelling of “OK”, and
These documents are usually updated whenever a new version of even a non-standard button being used.
the operating system or platform is released. So each time Apple
releases a new version of OS X, the Apple OS X Human Interface Here is the same interface, tweaked to follow User Interface
Guidelines are updated to reflect the changes in user interface Guidelines:
design. With each revision to the operating system, there are
often major changes (such as when Apple introduced the Aqua
interface or Microsoft added the Universal look to Windows), but
even minor changes add up over time.
220
As you can see, while both interfaces can accomplish the same
task, one will be much more pleasant to use (and is also likely to
be more consistent and stable).
Xojo helps you follow the guidelines by helping you position your
controls correctly (notice the blue lines that appear when you
drag a control near the edge of a window, for example).
http://en.wikipedia.org/wiki/Human_interface_guidelines
Although they can certainly make for some dry reading material,
it’s worth keeping a copy of them somewhere you can access it.
221
14.3 Creating A
Responsive Interface
Have you ever been using an application and wondered what it
was doing? Maybe you were trying to download a file, print a
document, or process an image. Often, an application will provide
you with some indicator of both its progress and how much time
remains. The applications that don’t provide any feedback often
give the impression that they are frozen or hung; as a user, this
The ProgressWheel, on the other hand, sends a different
can be very frustrating, as you must decide at which point you
message to the user. It essentially says, “I don’t know how long
stop waiting and force the application to quit.
this will take, but please be patient because I’m still working on
Think back to the controls you learned about in earlier chapters. it.” The ProgressWheel is better suited to situations where it is
Two controls that are excellent for providing feedback to the user difficult or impossible to guess how long something will take,
are the ProgressWheel and ProgressBar. If you recall from earlier, such as using a Socket to connect to a remote server or initiating
the ProgressBar is best used when you can quantify what your a database connection.
application is doing. In other words, if you are processing a
known number of records or can calculate how long a process
will take, the ProgressBar is a great fit. This is because it gives the
user an indication not just that something is happening, but how
much has happened and how much remains to be done.
222
The following project illustrates how to use a ProgressBar to keep 3) Run your project.
your user informed. The project will loop through 10,000,000
4) Click the PushButton and wait for the message box.
numbers and multiply each one by a random number. It’s kind of
It will take a few seconds, and in the meantime, your application will be
a silly example, but it’s a good approximation of the kind of data-
unusable and non-responsive. When the process is complete, quit your
intensive processing some applications need to do. You will
application.
create this project with and without a ProgressBar, so that you
can see the difference. 5) Add a ProgressBar to Window1. Position it so that it is as
wide as possible. Also give Window1 a new property:
Create a new Xojo desktop project and save it as “Progress”. Progress As Integer.
Note how the Thread and Timer position themselves below the Window
2) Add the following code to the Button’s Action event:
and all other controls (the Shelf). This is because they are not visual
Dim i, j As Integer controls; they have no visual interface for the user to see. You’ll learn more
Dim r As Random about Timers in the next section.
For i = 0 To 10000000
r = New Random 7) Change the code in the PushButton’s Action event to this:
j = i * r.InRange(1, 1000)
Next ProgressBar1.Maximum = 10000000
MsgBox("Done Processing!") ProgressBar1.Value = 0
Timer1.Period = 500
Timer1.Mode = Timer.ModeMultiple
This may be your first exposure to the Random class. The Random class,
Thread1.Run
as implied by its name, is used to generate random numbers. In this
example, you’re using its InRange function, which takes two numbers as
parameters and returns a number between those two numbers (in this case, This will set the ProgressBar’s Maximum and current value, set the timer to
between 1 and 1,000). run every half second, and tell the Thread to start running.
Dim i, j As Integer
Dim r As Random
223
For i = 0 To 10000000 12) Quit your application.
r = New Random
j = i * r.InRange(1, 1000)
Progress = i
Next
This is a slightly modified version of the code that was previously in the
PushButton’s Action event. For each number that the app processes, the
Window’s Progress property will be increased by one. Because this is being
done inside a Thread, the user interface will remain responsive throughout
the operation.
ProgressBar1.Value = Progress
If ProgressBar1.Value >= ProgressBar1.Maximum Then
MsgBox("Done processing!")
Me.Mode = Timer.ModeOff
End If
This will set the ProgressBar’s Value to be the value of the Progress
property that is set by the running Thread. The Thread cannot directly set
the ProgressBar’s Value because (due to operating system restrictions)
Threads cannot modify (or access) the user interface. The code displays a
message and stops the Timer when it has reached the maximum.
11) Again, click the Button and wait for the message box.
It still takes a few seconds, but this time, the ProgressBar lets you know
that something is happening and that the application isn’t stuck, frozen, or
crashed.
224
14.4 Making Things
1) Add a Label to Window1. Set its name to “ClockLabel”.
Feel free to position it anywhere you like, but make sure that its Width
UpdateClock
Create a new desktop project and save it as “Timers”. (the Shelf). This is because the Timer is not a visual control; it has no visual
interface for the user to see.
225
2) In the Inspector, make sure the Timer’s Mode is set to
Multiple and its Period is set to 1000.
The Mode can be Off, Single, or Multiple. When the Mode is set to Off, the
Timer is essentially dormant and won’t do anything. When the Mode is set
to Single, the Timer’s Action event will fire one time, and that’s it. When the
Mode is set to Multiple, the Timer’s Action event will fire repeatedly,
depending on the value of the Period property. The Period is set in
milliseconds, or thousandths of a second, so our value of 1000 will cause
the Timer’s Action event to fire about once a second.
UpdateClock
Notice that the clock now updates itself every second, whether the Button
is used or not.
226
list, which is displayed in another window. It may look something
14.5 Managing Windows like this:
So far, all of the projects and applications you have built have one
thing in common: they are all single-window applications. This in
itself is not necessarily a bad thing, especially since modern user
interfaces are trending more and more toward a single-window
philosophy (this is particularly true in the case of smartphone and
tablet interfaces). However, there will still be times when you need
to support multiple windows in an application. Fortunately, each
window you add to your project is really a class. This makes
managing them very easy, since you already know how to work
with classes.
227
6) Add a method called “PopulateNames” (with no parameters) With this code, the Button will be responsible for creating a new instance of
to ListWindow. DetailWindow which also displays it.
This will cause OKButton’s Action event to fire when the enter key is
This method’s job is to sort the names in the array and then add each one pressed and CancelButton’s Action event to fire when the escape key is
to the ListBox, using a For loop. Because it will be run multiple times, it will pressed (in both cases, the buttons still respond to mouse clicks, of
need to remove all existing rows from the ListBox first: course).
7) Add a public method to ListWindow called “AddName”. This 12) Add this code to CancelButton’s Action event:
method takes one parameter: name As String.
Self.Close
Names.Append(Name)
PopulateNames
CancelButton, when pressed, should close its containing Window. This
code makes that happen.
This method’s job is to add a new value to the Names array and then run
the PopulateNames method. 13) Add this code to OKButton’s Action event:
PopulateNames
OKButton has more work to do. It needs to take the text in NameField and
add it to ListWindow’s Names array, then close its containing window.
9) Add this code to the Button’s Action event: Since it needs to refer back to ListWindow, you might assume that you
need to create a variable for it, as you did with DetailWindow above. While
Dim w As New DetailWindow that would work, it would also create another instance of ListWindow when
the New keyword is used. Windows in Xojo feature something called
228
implicit instantiation, which is a fancy way of saying that if a window is
already open, and the application only needs one copy of that window, you
can access it by name at any time.
From there, you can enter names, which will be sorted and added to the
ListBox on ListWindow.
229
but it points to an object that doesn’t yet exist. This is, of course,
14.6 What To Do When easily fixed:
Another important aspect of the user experience is error handling. MsgBox d.ShortDate
230
With that in mind, your code should look more like this: Another common exception is the OutOfBoundsException. This
occurs when your code has tried to access an element of a list
Dim s As Student
(array, ListBox, etc.) with an index outside of the list. For instance,
s = GetStudent( 12345 )
If s <> Nil Then an OutOfBoundsException would occur if you try to access the
MsgBox s.BirthDate.ShortDate tenth row of a ListBox with only five rows.
End If
Most OutOfBoundsExceptions can be prevented with careful
That If statement, checking to see if s is Nil, can protect you and coding. For example, when looping through an array, consider
your users from a lot of pain. Even better would be to provide an using a For Each loop rather than a loop with a counter.
error message if s actually is Nil:
Of course, there are some exceptions that you can’t do much
about. One example is the OutOfMemoryException, which occurs
Dim s As Student
s = GetStudent( 12345 ) when the computer is basically maxed out and can’t spare the
If s <> Nil Then memory resources required for the task at hand. In such a case,
MsgBox(s.BirthDate.ShortDate)
the best you can do is try to recover gracefully.
Else
MsgBox("The student could not be found.")
End If
With these exceptions, and all others, a good rule of thumb is to
use the Try/Catch method. This allows you to attempt to run
some code, and also provide alternate code to use as a failsafe.
You might even include a message to contact tech support or
The Student example from above, for example, would look like
other appropriate people.
this:
The example above, however, only protects you if s is Nil. What if
s is a valid, existing Student, but the birthdate hasn’t been Try
Dim s As Student
defined for some reason? In that case, using
s = GetStudent( 12345 )
s.BirthDate.ShortDate will also result in a NilObjectException. This MsgBox s.BirthDate.ShortDate
is an example of something that should be handled in the Student Catch err As NilObjectException
MsgBox("The student could not be found.")
class itself, perhaps by providing a default date or dealing with
End Try
the NilObjectException there.
231
Everything in the top portion, under Try, is attempted. If a
NilObjectException occurs, the code in the lower portion is
executed.
232
Chapter 15
The
Rulebook
CONTENTS
1. Chapter Overview
This chapter will be different from the rest. Rather than providing
you with instructions for a sample project, this chapter will pose
some questions that are intended to be discussed by your class.
234
of what the client or user has described and go over it with them.
15.2 The Most Important Before you write a single line of code, make sure you understand
the problem that you’re trying to solve.
Things
Many computer developers get caught in what can be called the
Programmers’ Trap. After spending months or years learning to
write good code, and then spending more months or years
writing applications, many developers fall into the trap of thinking
that their job is writing code, but it is not.
235
Very often, the problem that needs to be solved will not be the mentioned above. It might be taking a paper process and moving
one specified by the client or user. In such cases, you will need to it online to make it faster and more efficient. Whatever the task is,
dig deeper. A classic example tells of a man who said he needed your job is to make your users' lives better, even if in very small
a hammer. Digging deeper into his story, it turns out that while he ways.
did need a hammer, that wasn't his real problem. He actually
FOR DISCUSSION:
needed to drive a nail into a wall. But that wasn't his real need
either. He actually needed the nail in the wall so he could hang a 1) When trying to determine the problem that needs to be
solved, what kinds of questions would you ask the user or
picture. And he wanted to hang the picture because he wanted to
client?
beautify his surroundings. When asked, the man said he needed a
hammer, but what he really wanted was art and beauty around 2) How would you handle someone who came to you with a
detailed solution already mapped out without specifying the
him. In the same way, you need to ask questions and dig deeper.
actual problem?
This leads into the developer's second main job: adding value.
Your work and your code should add value to the user's
experience. This can take many forms, such as providing art as
236
FOR DISCUSSION:
15.3 Don't Repeat 1) Why is the DRY principle more important than other
programming principles?
Yourself 2) What are the disadvantages to a WET approach?
As mentioned earlier in this book, one of the cardinal rules of
programming is Don't Repeat Yourself, sometimes referred to as
the DRY principle. The DRY principle means that if you have the
same code in more than one place in your application, you're
doing it wrong.
Also remember that if your code isn't DRY, it's WET. WET stands
for Write Everything Twice.
237
good reason, your user's permission, and a chance for your user
15.4 User Data Is Sacred to cancel.
You likely use an online email service like Gmail or Yahoo Mail. It's important to note that this applies only to user data. If your
Imagine logging into your account one day to discover that all of code generates some temporary files that no longer store
your archived messages were gone. How would you react? important data, those are always safe to delete. In fact, as in the
rest of life, it's a good idea to clean up after yourself. But data
Or imagine that you logged into Facebook only to find that all of
that the user has created or saved must be kept safe.
your photos had been deleted.
As stated above, before you delete user data, you need a very
Odds are good that you would be pretty upset in either case. Your
good reason. The most obvious reason is the user deciding to
users would be upset, too.
delete something. Another reason might be that the data has
expired. There may be others as well. An example of a bad
reason to delete user data is a programming error. If your
application deletes data for no good reason, you can rest assured
that very few people will use it!
You also need the user's permission. If the user has initiated the
deletion process, then you are probably clear on this one. If your
application started the process, then you need to make sure,
through a dialog box or other mechanism, that your user is
granting you permission to continue.
238
As a bonus, you might provide a method for the user to undo
deleting the data. This is not required, although it is very
common. If the deletion cannot be undone, it's a good idea to
warn your user of that fact when confirming the deletion.
FOR DISCUSSION:
239
15.5 The Principle Of
Least Astonishment
When you click on a PushButton labelled "Print", what do you
expect to happen? If you're like most people, you'd probably
expect something to come out of your printer (likely something
related to what's on the screen). What if you clicked a Print button
and the app quit? Or what if you clicked on a checkbox and the
application sent an email?
240
Bear in mind, however, that simple for the user does not
necessarily translate into simple for the developer. In fact, quite
often, the simpler the interface is, the more complex the code
behind it is.
FOR DISCUSSION:
241
himself or herself, because many times, the user is his or her own
15.6 It's Always Your worst enemy.
If the user is supposed to enter a date, don't just hope that they
enter it in the correct format. Some will use slashes and some will
use hyphens. Some will use the US format and some will use the
UK format. Some will use the business standard and some will
use the academic standard. Some will just go ahead and spell out
the month. If possible, use a third party date picker control or
provide some popupmenus to guide the user in entering the date.
The key point is this: if you allow your user to enter invalid data,
whatever happens after that is your fault. Allowing the user to do
something sends the message that it's okay to do it, so allowing
them to enter arbitrary text into a numeric field or a date field
without warning them tells them that you're going to parse the
That may sound harsh, but the reality is that you need to predict
data correctly. If you need the data in a certain way, make it easy
everything that could possibly go wrong and defend your user
against it. This usually also involves defending your user against
242
for the user to enter it that way and extremely difficult (if not
impossible) to enter it the wrong way.
You will be amazed at the things that users try to do with your
applications. Some of these things will be great ideas that you
can implement, but many of them will be things that quite
honestly make you scratch your head and wonder.
FOR DISCUSSION:
243
Because of this, you need to plan for the future. The best way to
15.7 Plan For The Future do this is to write your code to be read. This means that you
should use logical and consistent method, function, and variable
Most of the software you use isn't on the first version. Apple has
names. You should also stick to the DRY principle. And you
been working on its Mac operating systems since before 1984,
should comment your code extensively. Someday down the line,
and they've been working on iOS since before 2007. Microsoft
someone will need to update your code, and that person will
has versions of DOS and Windows stretching back decades as
need to be able to figure out how the code works. And there's an
well. Word, Photoshop, Firefox, Google Chrome, and Xojo have
excellent chance that person will be you. Remember that what’s
all been expanded, enhanced, and upgraded over the years.
fresh in your head now will likely be very stale a year from now.
Your code will likely need to be updated as well. Your application
So do your future self a favor, and write readable code now. And if
might not be used for decades like some of these examples, but
it's not you who has to maintain it, then you will be making some
the chances that it will be perfect and complete at version 1.0 are
other developer very happy.
very close to zero.
Another way to future-proof your code is not to make too many
assumptions. Write your code to be flexible. For example, you
may be writing an application that currently only has to handle
three files, but someday it might be more, and your application
should be ready for that with minimal or no code changes.
FOR DISCUSSION:
244
development relates directly to optimization: "We should forget
15.8 Get It Working First about small efficiencies, say about 97% of the time: premature
optimization is the root of all evil."
Another trap that many developers fall into is the optimization
trap. When this happens, a developer will repeatedly delay Perhaps Knuth was overstating things a bit for the sake of making
shipping the application while continuing to work on small, often his point, but it's a point worth making: don't get so caught up in
inconsequential speed improvements. But as Steve Jobs said, making your application faster that you never get around to
"Real artists ship." In other words, an application that no one but shipping it.
you ever uses may not count for much.
Knuth certainly wasn't alone in this opinion. His contemporary
Michael Anthony Jackson (not to be confused with another
Michael Jackson, the late King of Pop) said this: "The First Rule of
Program Optimization: Don't do it. The Second Rule of Program
Optimization (for experts only!): Don't do it yet."
FOR DISCUSSION:
1) What other items might you find in the spec for a basic email
client? And in the roadmap?
246
15.9 Documentation and
Help
One of the most vital pieces of any application has nothing to do
with your code: the documentation. It’s a virtual guarantee that
when you deliver the final build of an application, the users will
want documentation. Whether this is in the form of a printed
manual, a series of short tip sheets, screencasts, or an online
help system, documentation will give your users a sense of
security and confidence in your absence.
This may sound like a contradiction, but at the same time, you
should also strive to develop applications that are so simple to
use that very few users need the documentation.
FOR DISCUSSION:
1) What are some simple and practical ways you could include
documentation with a Xojo application?
247
Afterword
CONTENTS
1. Thank You
ccxlix
About The Authors
BRAD RHINE
When he’s not writing code or writing about code, you’ll find Brad
playing his guitar, hanging out with his family, or running.
He lives in rural Pennsylvania with his wife and their two children,
as well as a dog and two maladjusted cats.
PAUL LEFEBVRE
ccl
Copyright & License
This work is copyright © 2012-2016 by Xojo, Inc.
ccli