Events and Controls

From Real Software Documentation

Jump to: navigation, search

Aim In this lesson, we will continue our exploration of Real Studio’s Object Oriented Programming (OOP) features.

Contents

Events and Controls

In Lesson 9, we saw how events let us link the code defined in a superclass with code in its subclass. This is the same mechanism Real Studio’s built-in classes use to provide us with event handlers that we can add code to in a window’s Code Editor.
In this lesson, we will use the TextField’s events to make a new version of the TextField that will only accept numbers.

  1. Open a new project.
  2. Create a new class called NumEdit, with TextField as its superclass.
  3. Open NumEdit’s Code Editor and add the following code to the class’s KeyDown event handler:
If (Key > "0") and (Key < "9") then
Return False
Else
Return True
End if

The Key argument to the event handler represents the key that was just pressed. And the Boolean (True or False) return value from the event handler tells Real Studio’s built-in class what to do with they key that was just pressed: if the function returns True, the key is ignored; otherwise, the keystroke is processed normally.

In fact, functions in Real Studio always return something. If you don’t explicitly return a value, the function will return a suitable “zero” value (0, an empty string, False, Nil and so on, depending on the return type of the function). Notice that when you don’t provide an event handler in a subclass, when the superclass calls this function, Real Studio automatically returns the default False from the call. So, as you would expect, if you don’t provide a TextField subclass with a KeyDown event handler, it just processes every keystroke normally.

  1. Switch to Window1’s Window Editor and use the pop-up menu above the Controls list to switch the list from Built-in Controls to Project Controls.
    NumEdit is listed here.
  2. Drag the NumEdit class from the Project Controls list into the window, and run the program.
    Notice that it does almost what we want, but it doesn’t support the arrow or delete keys. We should really fix that.
    To do that, we need to know the ASCII codes for the keys we want to permit. We could go fishing around to find it in the documentation or online somewhere, but it is easier to just work it out for ourselves. Switch back to the Built-in Controls list and drag a regular TextField into the window, and add the following code to its KeyDown event handler:
MsgBox Str(Asc(key))

As usual, look up Str and Asc in the built-in reference if you need to.

  1. Now run the program, click on our new TextField, and notice the numbers displayed when you press the Arrow keys and the Delete key.
  2. Modify the code in NumEdit’s Keydown event handler to read:
If (Key >= "0") and (Key <= "9") then
Return False
elseif Key >= Chr(28) and Key <= Chr(31) then //arrow key
Return False
Elseif Key = Chr(8) then //delete key
Return False
Else
Return True
End if
  1. Run the program, and notice that our new TextField now lets us use the Arrow keys and Delete key.
    We can improve this class even more if we allow the user to enter a period for decimal values and a minus sign for negative numbers. In doing this though, we should make it work properly and let the user enter a period or minus sign once and then only in an appropriate place.
    Think about what might be involved in doing all this. Read about the TextField’s SelStart and SelLength properties.
  2. Modify the code to read:
If (Key >= "0") and (Key <= "9") then
Return False
Elseif Key = "." and InStr (Text, ".") = 0 then
Return False
Elseif Key = "-" and SelStart = 0 and Instr (Text, "-") = 0 then
Return False
Elseif Key >= Chr(28) and Key <= Chr(31) then//arrow key
Return False
Elseif Key = Chr(8) then //delete key
Return False
Else
Return True
End if

So we stop the user from entering a period or a minus sign more than once, and we only let them type a minus sign at the beginning. The TextField now works correctly, allowing the user to enter a valid number but nothing else.

A Further Subclass

Our next task is to create a subclass of NumEdit that won’t let the user enter a number higher than a set maximum value.

  1. Create a subclass of NumEdit called LimitNumEdit.
    You can do this by right+clicking (Control-clicking on Macintosh) on NumEdit in the Project Editor and choosing New Subclass from the contextual menu. Real Studio will create a new subclass of NumEdit and name it CustomNumEdit. Use the Properties pane to change its name to LimitNumEdit.
  2. Open LimitNumEdit’s Code Editor, and note that the KeyDown event handler is missing.

More on Events

A Event Definition is a method call that gets connected to an actual method somewhere else. Entering code into an event handler provides the actual method for the event to call. But it can only be hooked up to one event handler. In a chain of subclasses, the “highest” one to provide an event handler “swallows” the event, and doesn’t let any further subclasses see it.

This isn’t a problem, though, because there is nothing to stop the subclass that handles the event from defining a further new event, with exactly the same name and arguments as the one it is handling, and to call that at an appropriate time. Let’s see how to do that.

  1. Open NumEdit, and add a new KeyDown event definition, just like the original (same argument and return type).
  2. Modify the KeyDown event handler to read:
If (Key >= "0") and (Key <= "9") then
Return KeyDown(Key)
Elseif Key = "." and InStr (Text, ".") = 0 then
Return KeyDown(Key)
Elseif Key = "-" and SelStart = 0 and Instr (Text, "-") = 0 then
Return KeyDown(Key)
Elseif Key >= Chr(28) and Key <= Chr(31) then //arrow key
Return KeyDown(Key)
Elseif Key = Chr(8) then
Return KeyDown(Key)
Else
Return True
End if

Wherever we were permitting a key before, we instead ask our subclass to decide what should be done with it. If there is no handler, the default False value is returned, so the behavior is just as it was before if there is no subclass, or if that subclass provides no handler for this event. But if it does, it can further restrict the acceptance of keys.

But note that the way we’ve set up our events and the way we call them doesn’t give a subclass a way to accept more keys. If the superclass rejects a key, the subclass doesn’t even see it.

  1. Test that NumEdit still works.
  2. Change the TextField in the window to a LimitNumEdit control (by clicking on the TextField in the window and changing its Super in the Properties pane), and test that it still works.
    Since we added no code to it, it does exactly what its superclass does.

Consider now what might be involved in implementing a LimitNumEdit as we want. Now let’s do it.

  1. Add a Maximum property to the LimitNumEdit class, and a SetMaximum method:
Sub SetMaximum(M As Integer)
Maximum = M

We shouldn’t usually set the value of a property directly, so we created this setter method.

  1. Add the following code to the KeyDown event handler:
Function KeyDown(Key As String) As Boolean
Dim ChangedString As String
ChangedString = Left(Text, SelStart) + Key + Mid(Text, SelStart + SelLength + 1)
If Val(ChangedString) <= Maximum then
Return False
Else
Return True
End if

As usual, look up any of these text-handling functions you are unsure of.

  1. Add the following code to the Open event handler for the control in the window:
    Me.SetMaximum 500
  2. Run the project and test that it works as planned.
  3. For testing purposes, add a new “Boo” Event Definition to the NumEdit class.
  4. Create a new class FurtherNum, with LimitNumEdit as its Super.
    Notice that FurtherNum has a “Boo” handler. This works because LimitNumEdit doesn’t define an event handler for Boo (to make our terminology here clear: “not defining an event handler” means not having any code in the event handler).
  5. Remove the New Event Boo from NumEdit and remove its handler before you save the final version of this.
    You might also like to Export the NumEdit and LimitNumEdit classes out of the Project Window (select them and look for Export in the File menu or in their actual menu) to somewhere handy. These are our first actually useful classes, and you may well have need of them some day. You can just drag the files into the Project Editor in another project in order to use them again. Make sure you drag NumEdit in before LimitNumEdit, though. Otherwise, there will be nothing for LimitNumEdit to be a subclass of when it’s imported, and it will lose its superclass setting.

Further Exercises

Try some of the following exercises:

  • Implement a PositiveNumEdit subclass;
  • Use the LimitNumEdit class in a project with a window that performs an operation on two numbers entered, displaying the results in a third TextField;
  • The same, except with a set of radio buttons to choose the operation;
  • The same again, but it also updates the result as you are typing;
  • Implement a RangeEdit subclass, which defines a new WithinRange event, which is called when a number within a certain range is entered. You will also need to define suitable properties and a method to set the range.

Explanations/References:

Events are explained in the REAL Studio User’s Guide Chapter 5 (particularly in the section Adding New Events).

Personal tools