logo

 

     
 
Home
Site Map
Search
 
:: Bitwise Courses ::
 
Bitwise Dusty Archives
 
 
 

rss

 
 

ruby in steel

learn aikido in north devon

Learn Aikido in North Devon

 


Section :: visual basic

- Format For Printing...
From Encapsulation to Extender Objects…

VB6 - On The Move

Dermot Hogan finds poetry in motion as Visual Basic 6 controls follow him around.
Thursday 27 July 2006.
 

One of the more useful ideas in programming is ‘data hiding’. Fundamentally, you put information inside an object so that it can’t be modified or even seen from programs external to the object. This is taken to its extreme in Smalltalk, but even in a humble Visual Basic 6 program, it finds its uses.

(See also: Part 2 of this series)

This relates to what seems to be a basic fact of human psychology (and computer programming). Most people can hold only a half dozen of so things in their mind (their ’working memory’) at the same time. When you are writing a program, it’s quite common to think as you go along - ’I must fix that’ or ’this needs to be changed’. Of course, as the number of things ’to do’ grows, some things get forgotten - and become bugs. You can avoid this limitation to some extent by hiding functionality within a control or subroutine. If a single fact is all you have to remember about a subroutine – say, for example, that it dials a number - then you’ve got more working memory to hold other important facts.

Zip

In several ways, Visual Basic controls are like subroutines. But one of the major differences between a subroutine and a control is how data is passing into and out of them. Typically, you’d use a subroutine’s parameters to do this. With a control, you use ‘properties’. But there’s another difference. You can’t cheat by using global variables. In a Visual Basic subroutine, you can bypass the subroutine’s parameter mechanism by using a variable declared elsewhere:

Dim result as Integer
Sub bad(x, y as Integer)
 result = x*x + y*y
End Sub

This is usually a bad idea. A better way is to use all parameters like this:

Sub better(x, y, z as Integer)
z = x*x + y*y
End Sub

and call the calculation:

Call better(3,4,result)

An even better way, though is to use a function:

Function best(x, y as Integer) as Integer
 best = x*x + y*y
End Function

’Global’ variables (which is how the variable result is used in the first example) are often frowned upon by good programmers because they can lead to problems. Effectively, you are bypassing the encapsulation of the subroutine by adding extra data ’links’. The more links you have, the more things you have to be aware of and the more likely it is you’ll create a bug. Controls don’t have this problem. You can’t access a variable in your program from within a control and so you more or less have to use ’good’ programming techniques. But this leads to another problem: sometimes you really do want to get your control to access global program variables.

Following On

To see what the problem is, we’ll construct a simple program that deals with handling mouse events. Normally, the only mouse event you see is Click. But there are other mouse events that you can handle, MouseDown, MouseUp and MouseMove. The basic MouseMove event on a Form looks like this:

Private Sub Form_MouseMove
        (Button As Integer,
        Shift As Integer,
        X As Single,
        Y As Single)
End Sub

The first parameter, Button, tells you which mouse button was pressed, the second, Shift, indicates the state of the Shift, Alt and Ctrl keys, while the last two, X and Y give the co-ordinates of the mouse. I’ve written a little program that illustrates the use of the MouseMove event. In this program (Project1.vbp) the Follower control follows the cursor around when the mouse is moved while it’s in the form. The MouseMove code looks like this:

Private Sub Form_MouseMove
(Button As Integer,
Shift As Integer,
X As Single,
Y As Single)
Dim move As Integer
move = 5

If Follower.Left - X < 5 Then
   Follower.Left = Follower.Left + move
Else
   If X - (Follower.Left + Follower.Width) < 5 Then
   Follower.Left = Follower.Left - move
   End If
End If

If Follower.Top - Y < 5 Then
   Follower.Top = Follower.Top + move
Else
   If Y - (Follower.Top + Follower.Height) < 5 Then
   Follower.Top = Follower.Top - move
   End If
End If
End Sub

All it does is examine where the Follower button is in relation to the mouse and move it around a bit. Not exactly rocket scientist stuff, I’ll grant you. But suppose that, in line with the idea of using controls to achieve code encapsulation, I wanted to make the control do the moving - that is, move itself, rather than be moved by code in the form? This is a little more difficult. The problem lies in the fact that to move itself, the control has to know where it is in relation to the containing form: it has to alter its co-ordinates which are not its own property, but properly belong instead to the container.

Visual Basic gets round this problem by using a special object called the ’Extender’ object. The Extender object contains data that the container object knows about and which may also be of interest to the control (see below).

In the example here, we need to change the Top and Left properties of the Follower control to follow the mouse move. To do this, you have to add a new method, Mouse, to the Follower control which you can call from within Form1 when the mouse is moved. The MouseMove method in Form1 then becomes:

Private Sub Form_MouseMove
        (Button As Integer,
        Shift As Integer,
        X As Single,
        Y As Single)
        Call Follower.Mouse(X,Y)
End Sub

You’ll find the Follower Mouse method in the project in Project2.vbp. It’s very similar (as you might expect) to the original code.

Property Pages

Now we’ve got the Follower control to do its own moving, we can add a lot of other properties to the control that will modify that behaviour. For example, you might want to change the size of the movement by changing the move variable. Or you might want to ’repel’ the control from the mouse by altering the direction of the movement. You can add properties to the control (best done using the Control Interface Wizard), and then alter them via the Property window. But there’s another way - Property Pages.

Property Pages give you (the control designer) greater flexibility over how properties are displayed. For example, you might want to ensure that a related group of properties is altered in a consistent manner. I’ll illustrate Property Pages by adding a simple direction parameter to the Follower control.

First add the direction property: load the project Project2.vbp, select the ActiveX Control Interface Wizard from the Project menu and skip the Select Interface Members by choosing Next. In the Create Custom Interface Members, select New and add a new Property called direction. Click OK, Next, and Next, bypassing the Set Mapping screen. In the Set Attributes screen, select direction from the Public Name list box and set its Data Type to Boolean. Select Finish and finally Close.

Now we’ll use the Property Page Wizard. Select the Property Page Wizard from the Add Property Page menu. Skip any initial screen and from the Select Property Pages page click Add. Set the Property Page Name of the new property page to Movement. Click OK then Next. Now select direction from Available Properties and click > to transfer it to the Movement Property page. Select Finish to complete.

You’ll now see a new folder, ’Property Pages’ appear in the Project window. If you double click on the Movement item, you’ll get something that looks suspiciously like a form displayed with a check box labelled ’direction’. A Property Page is indeed a form and you can program it exactly like a standard data entry dialog box. This is clearly overkill for a single field, such as the direction indicator. But if you’ve got a whole set of fields which interact and need to be validated at design time, then using a Property Page will save a great deal of time and effort

You can use the Property Page code to program the movement direction directly - after all the direction value is set in the Property Page, but in this case there’s no real value in this. All this required is to modify Follower’s Mouse code:

If direction = False Then
 move = 5
 Follow.Caption = "Following"
Else
 move = -5
 Follow.Caption = "Retreating"
End If

Now if you close Follower’s design window and right mouse click on the Follower control in Form1, you’ll find a Properties menu item at the bottom of the pop-up menu. Click on this and you’ll see your new Property Page with the ’direction’ check box ready to be filled in. You can find the completed project in Project3.vbp.

It may not seem much of a gain to move the code to do with movement into a control, but the point is that once you’ve done this, you don’t have to think about it ever again (well, not often). Not only that, but your complete control is available in the Toolbox for instant use.

Next month, I’ll put our newly mobile controls to good (if rather unusual) use.


The Extender Object

The Extender object is always guaranteed to have a small set of properties, whatever the container.

These are:
- The Name property, the user-defined name of the control.
- The Visible property, specifies if the control is visible or not.
- The Parent property, a read only object that represents the container of the control, such as a form in Visual Basic.
- The Cancel property, indicates that the control is the default Cancel button for the container.
- The Default property, indicates that the control is the default button for the container.

In addition, the when Visual Basic is used as the container (that is you use the control from within a Visual Basic program), the Extender object will also contain, among others, the following:
- The Enabled property, a read only Boolean that specifies if the control is enabled.
- The Height property
- The Left property
- The Tag property, a read/write String that contains a user-defined value.
- The Top property.
- The Width property

The Extender object is a little different in its behaviour to other standard Visual Basic Objects. Because Visual Basic doesn’t know anything about the container that the object will be running in when the control is compiled, it can’t show a set of properties when you are designing the control. In effect, the Extender properties are added at run time - a technique known as ’late binding’.

You can also have non-standard properties in the container, but accessing these via the Extender object will make your control container specific. While there’s nothing wrong in doing this, you should be aware of what you’re doing and why you’re doing it.

Zip

AddThis Social Bookmark Button

Forum

  • VB6 - On The Move
    14 March 2009, by Joaquim

    when i compile the object, using the Extender object, why, where i use the Extender object, i have an error? thanks

  • VB6 - On The Move
    27 July 2006, by Steven

    EEEK.... we can’t have this!

    routine(x, y, z as Integer)

    In this scenario, only the last of these will actually be integers in VB as the first two will default to being variants ....

    • VB6 - On The Move
      27 July 2006, by Dermot Hogan

      Dead right!

      One of my sloppy bits of old VB code ... amazing what you could get away with then.

      Brings back memories ...

      • VB6 - On The Move
        29 July 2006, by Steven

        hehe, I can’t really say anything ..... I was just as bad if not worse when I first started with VB

        I tended to not only do as mentioned, but also leave out the oh so wonderful "Option Explicit" - enabling it by default a few weeks after starting, was the best thing I ever did. Saved me a ton of debug time.

        Alas over the years I’ve tended to remember to do things properly (most of the time) though. My god do I feel old now ... lol.


Home