Chapter 3: Adding Labels

Showing Information with a Label

Your programs will need to do a lot more that just display a blank window! At the very least, the program needs to convey some kind of meaningful information to the user and 'labels' are one of the basic ways of doing this. As well as discussing how to display labels in your programs, this chapter will also introduce memory variables; an important tool in programming.

In order to keep each chapter to a reasonable length from this point onwards, I will focus on explaining any changes to the code covered in previous chapters as well as explain the new concepts, capabilities and code being introduced. To make these easier to identify, the new or changed code will be highlighted in yellow in the code listings included at the beginning of each chapter.

As with chapter 2, the first step is to write, compile and run the program so that you gain hands-on experience creating the code file and can see how it looks when the program runs.

Using your chosen editor, enter the code exactly as below and save the file to the MySourceCode folder naming it HMGGuide-Ch1.prg then compile the program using the "..\build HMGTuror-Ch1" command.

  #include "hmg.ch"

  FUNCTION Main()

  LOCAL cMainWinTitle := "ePortfolio"
  LOCAL cLabel1 := "Hello World! This is my second program..."

  DEFINE WINDOW Win_1 ;
    AT 0,0 ;
    WIDTH 760 ;
    HEIGHT 640 ;
    TITLE cMainWinTitle ;
    WINDOWTYPE MAIN

    DEFINE LABEL lblHello
      ROW 32
      COL 64
      VALUE cLabel1
      AUTOSIZE .T.
      FONTNAME "Lucida"
      FONTSIZE 16
    END LABEL

  END WINDOW

  ACTIVATE WINDOW Win_1

  Return Nil

You can download a copy of the source code file  from here -  HMGGuide-Ch3.prg

Introducing Variables

At the beginning of this chapter, I said that variables were an important tool in programming. In fact, it would be quite difficult to write any program that didn't use them, so it's really important to understand what they are and how to use them!

The easiest way to 'picture' a variable is to think of it as being a small 'box' in the computer's memory that contains a piece of information that may be used by the program to perform certain actions. For example, the information contained in the 'box' might be used to display some information on the screen.

The name 'variable' also suggests that the contents of the 'box' can be changed and, in many cases, it does. We'll explore how to change the information stored in a variable in Chapter 6 once you have developed a little more knowledge and experience with using them.

Before we move on to look at the variables introduced in this chapter, it is worth restating that my aim in this guide is to try and introduce new concepts gradually rather than possibly confusing readers by exhaustively covering each concept as soon as it appears! The chapters that follow radually build your knowledge of variables and in Section 2 – Fundamentals – I provide a chapter dedicated to the subject containing much more detailed coverage of the various types of variable and how to use them.

Creating LOCAL Variables

In this chapter, two variables are being created and each is given a value which is the piece of information the program will store in memory for the program to use. The following two lines of code are where this takes place.

LOCAL cMainWinTitle := "ePortfolio"

LOCAL cLabel1       := "Hello World! This is my second program..."

To understand this further, let's explore each part of the lines of code working from left to right.

The LOCAL statement  instructs the program that you are creating or, to give it the correct term, defining a variable that will only be visible within FUNCTION Main(). That means that only this function will know about the existence of this variable and be able to access it. This is known as the scope of a variable which, quite simply, refers to which parts of a program can see and use the variable. This may initially sound strange given that our program only contains one function but it will become clearer in later chapters when we create other functions. For now, all you need to remember is that when you define a LOCAL variable only the function where  it is defined is able to 'see' and use the value contained in it.

cMainWinTitle and cLabel1

Each variable you define needs to have a unique name and, in this case, the names being used are cMainWinTitle and cLabel1. It is good practice to try and name these in an obvious way and try to indicate the data type of the information the variable is going to contain. A data type refers to the various types of information that can be used in programs, for example, dates, numbers or letters. By starting the name of each of these two variables with a lowercase 'c', I am indicating that they are going to contain letters from the alphabet or 'characters'. If I intended the variables to contain only numbers, I would use a lowercase 'n' which stands for numeric or, if they were to contain dates, I would use a lowercase 'd' at the start of the variable name.

:=

This is known as an assignment operator. An operator is character or characters that instruct the program to execute a certain type of action. For  example, the + operator is used for addition, the  operator for subtraction, the / operator for division and the * operator is used for multiplication. In this chapter, we are using the assignment operator := to instruct the computer to assign a value to each of the two variables.

"ePortfolio" and "Hello World! This is my second program..."

These two sets of characters are the values that are actually assigned to each of the two variables. Technically, these are known as character strings and it is important to note that character strings must be enclosed in inverted commas although these inverted commas are not actually included as part of the value assigned to the variable.

Using a Variable

It is all well and good being able to define a variable, but that is pointless unless you actually use them in your program! If you look at the source code for this chapter, you will notice we have changed the way we wrote the TITLE instruction when defining the window. In the previous chapter we wrote the name of the window title to be displayed, enclosed in inverted commas, immediately after the TITLE directive. This is known as hard coding which should generally be avoided in your code as this makes the process of updating your code in future far more difficult.

In the previous chapter, we had hard coded the main window title but in this chapter we are directing the computer to use the variable we defined at the start of FUNCTION Main() by using TITLE cMainWinTitle to define the main window title. This might not sound especially useful at this stage but imagine if you wanted to display the same information in several places or even change that information! Using a variable makes this process much easier as you will see in later chapters.

The practice of using variables to contain values we use within our programs continues later in the program, and from this point onwards, when we display a label which is explained next.

Understanding the Label Definition

If you review the code we are using for this chapter, you will notice that we have included a new section of code within the definition of WINDOW Win_1 where the DEFINE LABEL ... END LABEL code has been included before the END WINDOW statement.

A label represents information that the user can see when the window is displayed and they belong to a group of programming items known as controls. As the name 'control' infers, these are used to provide the user with a level of control over the program. In fact, it is possible to make the label 'clickable' so that a certain action is performed if the user clicks on it but it's a little too early to go into detail about that just yet. For now, let's concentrate on understanding the basics of defining and displaying a label.

DEFINE LABEL lblHello

This code instructs the program to start defining a label which is called lblHello. It is important to remember a couple of simple rules when you define any control in a program. Firstly, all of the properties of a control included as part of the definition must be enclosed (or encapsulated to give it the correct term) between a DEFINE and an END statement. Secondly, all controls must have a unique name.

ROW 32 and COL 64

The ROW and COL properties are used to define where the top, left corner of the label will appear within the window that the label is associated with. Each of these requires an argument to represent the actual location (remember that an argument is simply a value that must be passed to a property). In this case the value of the two arguments is 32 and 64.

You will note that these two arguments have been hard coded. Deciding whether to hard or soft code property arguments is a balancing act and will depend on the requirements of your program. If you are designing your program to only display the label at one specific location and decide that the location won't need to change, then hard coding the argument values may be simpler and more efficient than using more memory by creating variables for the location. Having said that, I would still encourage you to develop your knowledge by experimenting later on by changing the ROW and COL properties to use variables instead!

VALUE cLabel1

The VALUE property, in this example, uses the contents of the variable cLabel1 to display the information the user actually sees on the screen wherever the label is placed. As before, deciding between using a variable or hard coding the value of the argument is a balancing act and you might decide that a hard coded value is simpler and more efficient when you write your own programs.

AUTOSIZE .T.

This property instructs the program to automatically use as much space as is needed within the window to fully display the contents of the label. The program will calculate how much screen space it needs below the ROW property and to the right of the COL property. It is possible to change this and define exactly how much space to use but, for now, I recommend that you use the AUTOSIZE property.

You will also notice that AUTOSIZE property is passed a value! In this case, it is passed a logical value which is, quite simply, a value that is either true or false. If it helps, think of true as meaning "yes" or "on" and false as meaning "no" or "off". This logical value is represented by .T. for true ("yes" or "on") or .F. for false ("no" or "off"). The full stop used before and after the letter representing the value is important, so ensure you use them.

FONTNAME "Lucida" and FONTSIZE 16

These two properties should be fairly obvious! You don't have to include them (a default font and size will be used instead) and you can change these to any valid font or size that your computer is capable of displaying.

Before we move on to the more enjoyable aspect of learning to program, experimentation, I want to reassure you that is isn't strictly necessary to really know all the correct programming terminology I have been using up to this point. I'm sure you probably find it a little confusing understanding the differences between an argument and the value of an argument and, if the truth be told, sometimes I mix the two up myself! I prefer to concentrate on the actual value I am passing to any property, and how that will affect the program, rather than think of it as being a value I am passing as an argument to the property.

A Little More Experimentation

I hope by now that you agree that experimenting with your code is the best way to become more familiar with the HMG language and its usage! In the first chapter I introduced ways in which you could start experimenting with your code by suggesting you change some of the argument values you passed to some of the properties you have been using or by suggesting some additional properties you could try (such as NOSIZE).

In this and in most of the subsequent chapters, I will suggest a couple of additional capabilities for you to try as you continue to experiment and explore HMG yourself. Whilst these should be largely self-explanatory, I will briefly explain where each should go and what it should do.

FONTNAME "Lucida" and FONTSIZE 16

Firstly, try increasing or decreasing the font size and experiment with other fonts such as "Courier", "Arial" or "Ravie". Any font installed on your computer (for example by MS-Word) should be displayed. Also try removing these two properties, to see the default font and size settings.

FONTBOLD <lValue>FONTITALIC <lValue>FONTUNDERLINE <lValue> and FONTSTRIKEOUT<lValue>

Start by adding a FONTBOLD .T. property to the definition of lblHello (below the line VALUE cLabel1 explained above). This will, obviously, display the label in a bold font. Try each of the other properties suggested above, or even a combination of them, remembering that each needs a logical argument value (as explained when you used AUTOSIZE) and that each should appear on a single line.

ROW and COL

Create two new numeric variables and use these to specify the row and column that your label will be displayed at. The changes you will need to make are to declare the two variables and assign them a numeric value (as below) and then use these variable names instead of the hard coded values used in the original label definition (as below).

LOCAL nRow := 150

LOCAL nCol := 80

  Instead of ROW 32 and COL 64 use ROW nRow and COL nCol.

CENTRE WINDOW <window name>

Add a CENTER WINDOW Win_1 command to your code after the END WINDOW statement, save the source code and re-compile it. The window will, obviously, be displayed in the centre of your screen rather than in the top, left corner of the screen.

Chapter 2: The Launch Program <<     >> Chapter 4: Display a Button