Image of Navigational Map linked to Home / Contents / Search 95 Style Status Bar for Windows 3.11

by Allan Nielsen
Image of Line Break

As a software developer working for a large organisation that is unable to convert all their PC workstations to 32-bit environments it has become difficult to ensure visual integrity between the 16-bit GUI interface on the workstations and the 32-bit server applications. This lead our team to construct a group of controls that emulate the functionality of the new 32-bit 95 style controls.

This control must behave in the same fashion as the 32-bit control, with the same properties, methods and events.

Status Bar Class

Add a class module to the project with the following attributes:

Instancing:2 - Creatable multiuse
This class is the only part of this 'control' that the user will be able to access once created. This class object will control the Status Bar behaviour and will also make available the subordinate class objects to the user.

Start by entering the code for the main Status Bar class object. This will provide the interface for the user. The code is provided as. All 32-bit properties have been catered for as well as an extra set of properties to allow the user to set/get the object chosen to be the status bar. This control must be a Picture Box. The Canvas Set/Get property combination provides this ability. The Set Canvas property first ensures the object type is a Picture Box, and if so, sets up the picture box with all the defaults required, Style: normal, BorderStyle: None, Alignment: Bottom, Visibility and Enabled: true. In the process of being declared the canvas property also initialises the Panels collection class and adds the 'Simple' panel (displayed using the Status Bar Style property).

Panels Class

Add another class module to the project with the following attributes:

Instancing:0 - Not Creatable
This class makes the Panel Object available to the User.

The Panels class provides 5 functions used throughout VB to manipulate Object classes. These are Add, Clear, Count, Item, and Remove. It also provides an extra Parent Set/Get property enabling the status bar control to pass information to the subordinate panel objects. NOTE: - This is a property not supplied in the 32-bit version and the value should only be set by the Status Bar class. The code for this class can be found in Listing 2.

Panel Class

Add another class module to the project with the following attributes:

Instancing:0 - Not Creatable
This class stores each property and method for each panel the User creates.

The Panel class provides properties for each panel. These are displayed in Listing 3, and as with the status bar and panels class, a detailed description of all of the properties, methods or events look in the VB help file or Online books provided with Visual Basic 4.

Resource Form

This form's specific purpose is to supply the Status Bar control with the required controls. It allows the Status Bar to capture the status of the Number Lock, Caps Lock, Scroll Lock and Insert keys, provide a timer for the Date/Time panel object and provide a canvas to draw the panel appearance before copying it to the main status bar on the User's form. Each 'key type' has a property Set and Get to enable each of the key types. The 'key type' (ie CapsLock_Change) change event enables or disables the panel object associated to it. The timer control Timer event supplies the text for the Date/Time panels. The code for this form is supplied in Listing 4.

Constants module (optional)

Add a module to your project and enter the constants from Listing 5. These are used within the Status Bar classes to allow easier reading and debugging, they are not a necessity, and you can place their value in the code instead making the need for the constants unnecessary.

Test form (not to be included in the control)

A test form (Listing 6) has been included here to demonstrate how easy it is to incorporate a status bar control with a project. The lines displayed in upper case are lines that must appear in the shown locations for the status bar control to behave correctly. The lines displayed in italics are copied straight from a help file example for the 32-bit status bar to demonstrate that once declared, the control behaves the same as the 32-bit control supplied with Visual Basic 4 32-bit editions.

An extended explanation

There are some private functions with the classes that may need further explanation as they are not standard properties of the 'control', but are used however, to display the status bar correctly.

DrawSimple routine (Status Bar class)
This routine is used to display the 'simple' style status bar. It was included within the main status bar class because it does not require any panel objects to be defined. It also makes the code more readable as no extra if statements are required in either the Panels or Panel classes.

SetSpringWidth routine (Status Bar class)
This routine is used exclusively by the status bar refresh routine to determine the width of the panel set as the 'Spring' panel in the Panel Style property. The spring panel will size itself to fit in the remaining gap left once all other panels have been sized, but will not reduce below it's minimum size.

DrawPanel routine (Panel class)
This routine is used, in conjunction with the resource form, to draw the panel using the panel properties. Once drawn it is copied directly to the status bar at the position set previously by the status bar refresh routine.

A Cautionary Note.

I originally wrote this object as an in-process-server, having no problems with its functionality. But a co-worker decided it would be better as an out-of-process server, as all our applications could use this object, and compiled it as such. I thought it was a good idea and that evening I wrote the article, Server untested. But an ugly problem arose...

Problem definition:

During the Canvas Set routine in the Status Bar class several picture box properties are set (Height, Align, Borderstyle) which trigger the picturebox Resize or Paint events. These events call the Status Bar refresh routine which is entered, does nothing as the picture box is still not visible and leaves the routine. But when the Canvas Set property code finishes a GPF arises. If the two refresh calls are commented out during the form load and replaced after the form has loaded and displayed, no fault arises.

Problem Scenario:

Current call sequence:

  1. Form_Load
  2. Canvas Set (Status Bar)
  3. PictureBox_Resize
  4. Refresh (Status Bar)
  5. Exit Refresh (Status Bar)
  6. PictureBox_Resize
  7. Refresh (Status Bar)
  8. Exit Refresh (Status Bar)
  9. PictureBox_Paint
  10. Refresh (Status Bar)
  11. Exit Refresh (Status Bar)
  12. Finish Canvas Set
  13. GPF

Other sequence:

  1. Form_Load
  2. Canvas Set (Status Bar)
  3. Finish Canvas Set
  4. No GPF

If I break the code to replace both refresh event callers (Picture Box Resize and Paint) the status bar works correctly. There is no 'recursive' calling being done. It seems to me that if an event is fired, calling a routine in the Status Bar class while one is already being processed, this will create a GPF. Further testing also showed that the Toolbar, ListView and Treeview all had the same problem during loading but worked fine once running.

We investigated the problem further and found that if you change the Paint and Refresh events to read:

Private Sub StatusBar1_Paint()
  If me.visible  and StatusBar1.Visible Then StatusBar1.Refresh
End Sub

Private Sub StatusBar1_Resize()
  If me.visible  and StatusBar1.Visible Then StatusBar1.Refresh
End Sub

This will ensure the call to the refresh event doesn't occur till the form is loaded and displayed. Thus avoiding the problem of the recursive recall.

Jim Karabatsos comments...

If you're trying to create an out-of-process server that updates a picture control with status bar information, you're in for some problems to do with the protection of windows objects (notably the device context of the picture box) in Win32.

For this sort of thing, I would strongly suggest that you stick to an in-process server. There is really NO advantage in using an out-of-process server here anyway, because Win32 will share DLLs loaded across process boundaries automagically. There is no memory penalty and (in Win32) there are no effective limits to the number of timers you can have. Additionally, you save on the context switch involved in calling an out-of-process server.

The basic rule of thumb is : don't pass VB controls across process boundaries. VB will get angry and tell your mother.


Image of How-To Icon Listing 1
Listing 2
Listing 3
Listing 4
Listing 5
Listing 6
You can download all the related files for this article at our web site as

Written by: Allan Nielsen
March '97

Image of Arrow linked to Previous Article Image of Arrow linked to Next Article
Image of Line Break