Status Bar DEMO - Version 3.00

By:  M. J.  Rodriguez     CIS ID: 100321,620
                        Internet: 100321.620@compuserve.com
                                  jrodrigu@cpd.hqusareur.army.mil


This compressed file contains the following files:

CONSTANT.GLB	- A supporting file for the demo
FORM1.FRM 	- Demo Form for the project
FORM1.FRX	- VB Support Graphic file for FORM1.FRM
README.TXT	- This File
SBARDEMO.EXE	- Executable of the Demo
SBARDEMO.MAK	- Project MAK file
STATBAR.BAS 	- Status Bar Module you need for any status bar
STATBAR.BMP	- BMP file used for the SBAR_MINICON Panels

Contents:
-------------------------------------------------
About the Code
Status Bar Implementation
How the Status Bar is Drawn
Adding the StatusBar to your project
How the Code Works
Use of the Status Bar with Menu's and Mouse Movements.
VB 4.0
Disclaimer
-------------------------------------------------


About the Code:
-------------------------------------------------

In early May I put out a project in CompuServe for a status bar that could be 
displayed using just a label, a timer, and a picture box.  Then a week later, 
I modified it by removing the label and just went with the timer and 
PictureBox.  Suffice it to say, I have had over 1000 downloads of it and have 
received many compliments.  Then as always, it doesn't quite meet just what 
the user wants and so the questions came in.  This third iteration is the 
result of some of those requests and includes some tips, although modified 
here, from other users.  Unfortunately, I cannot find the name of the few who 
did send in suggestions and additions, but if you see it again, I apologize 
for not including your name... however, VC..(you know who you are because I 
remember your initials), you get credit for the SBAR_FIXEDTEXT which was a 
great idea and your code is included.   The person who sent me the SBAR_BUTTON 
idea (without the code, so what you see is what I did) you get at least 
partial credit for it.  And a special thanks to the Los Angeles Visual Basic 
User's Group for their many kind comments.  I hope this will get added to your 
Top Ten list again.

I have modularized this code to the point where you should be able to just 
drop it into your projects and go.  If you have any problems let me know.


Status Bar Implementation:
-------------------------------------------------

In this concept, the Status bar is divided into panels.  Each panel is drawn 
individually.  Each panel has properties which you can change.  How you change 
the panel is determined by your needs.  The properties are kept in an array of 
a user-defined type called PanelType.

Here is the structure of PanelType..

Type PanelType
    sCaption As String          'Caption contained in the panel
    PanelStyle As PanelStyleType 'Panel Information
    iFontBold As Integer        'Whether or not font is bold
    iFont3D As Integer          'Whether or not font is 3D
    sFontName As String         'Font Name - Defaults to statusbar setting
    sFontSize As String         'Font Size - Defaults to statusbar setting
    lFontColor As Long          'Font Color - Defaults to statusbar setting
    bVisible As Integer         'Let's you hide or show any panel you wish
End Type


The PanelStyle element is a user-defined type called PanelStyleType.  There is 
no particular reason why I did it this way other than to isolate some 
properties.  In the original implementation, the Status Bar passed the 
PanelStyle element for drawing purposes.  Now, it isn't done that way, so 
instead of changing it to be one complete element, I left it the way it was 
and expanded it.  Probably not good coding, but it works.  Here is the 
PanelStyleType.


Type PanelStyleType
    iLeft As Integer            'Left Position of the panel
    iTop As Integer             'Top position of the panel
    iWidth As Integer           'Width of the panel
    iHeight As Integer          'Height of the Panel
    iBorderStyle As Integer     'Type of panel 0-Recessed, 1-Raised, 2-Flat: User Defined
    iFormat As Integer          'Format of the panel - Text, Date, Time, etc...: User Defined
    iTextFormat As Integer      'Format of Text in the panel VCENTER, CENTER, etc.: User Defined
    iOther As Integer           'Used for Icon Information or Percentage in the Meter Bar
    lOther As Long              'User for color of the meter bar or whatever else needs to be used
End Type


These properties change as you need them to.  Once they are changed, they will 
be reflected the next time the panel is drawn.

The following are the types of panels as defined by global constants.  These 
are not the only types you are limited to as you certainly can add any type 
you want.  It's entirely up to you.


'Format of the panels
Global Const SBAR_TEXT = 0            'Panel just contains text
Global Const SBAR_DATE = 1            'Panel contains the date
Global Const SBAR_TIME = 2            'Panel contains the time
Global Const SBAR_WEEKDAY = 3         'Panel contains the weekday
Global Const SBAR_FULLDATE = 4        'Panel Shows date as Tuesday Jan 1, 1995
Global Const SBAR_CAPSLOCK = 5        'Panel is a CAPLOCK toggle display
Global Const SBAR_NUMLOCK = 6         'Panel is a NUMLOCK toggle display
Global Const SBAR_SCROLL = 7          'Panel is a SCROLL LOCK toggle display
Global Const SBAR_COUNTER = 8         'Panel is a counter display
Global Const SBAR_FIXEDTEXT = 9       'Panel contains a fixed text
Global Const SBAR_MINICON = 10        'Panel is a miniature icon display
Global Const SBAR_ICONMIX = 11        'Panel is a miniature icon/text display
Global Const SBAR_BUTTON = 12         'Panel will emulate a button and fire and event when clicked
Global Const SBAR_METER = 13          'Panel is a meter control that displays progress

The SBAR_MINICON and SBAR_ICONMIX are unique in that they reference small 
icons.  In reality, I use another PictureBox names sbar_pics and include a 
single bitmap of all the small "icons" I want to use.  The individual pieces 
of the bitmap are 16 x 16 pixels and drawn using PaintBrush.  The program 
makes the assumption that you will do the same otherwise, the pictures may not 
come out correctly.  In the project, you will need to add at least one picture 
box named sbar_pics.  It doesn't have to big and can be invisible.  If you 
don't want to add the sbar_pics PictureBox, then remark out or delete all the 
references in the code that work with these types.  Most of them are in 
Select..Case statements and a few If..Then..Else.. blocks which are easily 
remarked out.

The panels are displayed in one of three ways: Flat, Raised, or Recessed.  
Here are the constants used in the implementation.

Global Const SBAR_PANEL_RECESSED = 0
Global Const SBAR_PANEL_RAISED = 1
Global Const SBAR_PANEL_FLAT = 2

By setting the iBorderStyle element in the PanelStyle UDT, you determine what 
the appearance of the panel will be.


How the Status Bar is Drawn.
-------------------------------------------------

The Status Bar is drawn using the DrawText API call and the Line Method.  Each 
panel size is determined by a number of conditions.  Every panel except 
SBAR_TEXT, SBAR_ICONMIX, and SBAR_METER is determined by the size of the 
element being displayed using a predefined format.  For example, the 
SBAR_FULLDATE size is determined by the width of the text of a formatted 
string containing capital X's and usually is represented the largest character 
count of the possible text.  This allows for constant size.  The SBAR_TEXT and 
SBAR_ICONMIX are displayed if any space is left over after all the fixed sized 
panels are subtracted from the available width minus the size of the border of 
the status bar around the panels and the gaps between each panel.  SBAR_METER 
is a globally defined constant which can be changed by you.  It is currently 
set to 100 pixels in width.  Here are the constants used in determining sizes 
of borders and gaps.

Global Const SBAR_BORDERSIZE = 2      'Space between StatusBar borders and panels in pixels
Global Const SBAR_PANELGAP = 4        'Gap between panels in Pixels
Global Const SBAR_TEXTGAP = 1         'Gap in between the text and the border in pixels
Global Const SBAR_METERWIDTH = 100    'Width in pixels of the Meter panel

These measurements are determined by you and will affect the size of the 
status bar's height.  Width is automatically decided as the status bar is 
anchored to the bottom of the form.  This can be changed by adjusting the 
Align property of the StatusBar control.


Adding the StatusBar to your project
-------------------------------------------------

First thing, decide which form or forms your Status bar is going on.  You 
aren't limited to just one form.  You can have a status bar on any form you 
want or as many.  There may be a performance sacrifice if you have like GOBS 
of forms with Status Bars, but whatever makes you happy, I always say...

If this is not a MDI form, and you have panels for CapLock, NumLock, or 
ScrollLock, or add anyother toggle function, then you want to change the forms 
KeyPreview property to True and then add in the Form_KeyDown procedure the 
follwing snippet:

	UpdateKeyPanels StatusBar, sb_panels()

This procedure takes care of just toggle keys.  If you have an MDI form, 
obviously, you can't use this because there is no KeyPreview property.  
The Timer procedure does take care of this.


In the Forms Declaration section of the form, add the following:

	Dim sb_panels() As PanelType
	Dim sb_initialized As Integer

The sb_panels() is for the status bar for that form.  For any other form, just 
add the same thing.  It doesn't matter.

You will need to add a procedure in the General Declarations section called 
CreatePanels.  A remarked out copy of the procedure is available in the 
General Declaration Section of the STATBAR.BAS file. You can use it as a 
template for your setting properties and the number of panels you want to 
create.  You can also use the copy that is available in the sample project.  Just 
look in the general section and look for the CreatePanels procedure.  A simple 
cut and paste will make it real easy to add.

In the Form_Load event, you will need to add the following code snippet.

	Dim bSuc%

	CreatePanels
	bSuc% = InitializeStatusBar(Me, sb_panels())
	sb_initialized = True

Now you are ready to add the status bar to your project. In the form,  you 
need to add a picture box to your form.  If this is a MDI form, it will be 
auto-aligned to the top.  It can be changed programatically later so don't 
worry.  Set the Name property of the Picture box to 'StatusBar'.  That's all 
you need to do with it.

In the StatusBar_Resize Event, add the following snippet:

	If Me.WindowState <> 1 Then
	    If sb_initialized Then DisplayStatusBar Me.StatusBar, sb_panels()
	End If

If you are using the SBAR_BUTTON panel, then add the following code to the 
StatusBar_MouseDown  and StatusBar_MouseMove procedures:

	SBarMouseDown StatusBar, Button, Shift, X, Y, sb_panels()

then add the following snippet to the StatusBar_MouseUp procedure:

	SBarMouseUp StatusBar, Button, Shift, X, Y, sb_panels()

These procedures have been setup to deal with the SBAR_BUTTON type panels.

Once you have done this, now add a timer and set the properties to the 
following:

	Enabled   True
	Interval  200
	Name      StatTimer

In the StatTimer_Timer procedure, add the following snippet:

	UpdateTimePanels StatusBar, sb_panels()

unless you are using an MDI form, then you want to use this procedure:

	UpdateStatusPanels StatusBar, sb_panels()

which takes care of the toggle keys you want to use.


The last control you need to add is another picture box for the SBAR_MINICONS 
if you want them in your project.  Add the PictureBox and set the following 
properties:

	AutoRedraw  True
	AutoSize    True
	Name        sbar_pics
	ScaleMode   3 - Pixel
	Visible     False

The Picture property does not have to be set at design time, but it's up to 
you.  Again, if you don't want to use SBAR_MINICONS or SBAR_ICONMIX, then 
don't add the controls and remark out the lines that perform operations on the 
sbar_pics control.


How the Code Works
-------------------------------------------------

The process involves, first, initializing the status bar by creating the 
panels and then actually drawing the initial status bar.  Then as changes to 
the status bar panels occur, they are redrawn.  They are redrawn on an 
as-needed-basis, meaning that if the information changes in the panel, it is 
redrawn and only redrawn for that panel.  The whole status bar does not have 
to be redrawn unless the user resizes the form.  In this case, the resizing is 
necessary because some parts of the status bar will go away and in order for 
the user to see it, it has to be redrawn.  The dynamic panels of SBAR_TEXT and 
SBAR_ICONMIX will adjust sizes if the status bar changes width.  What this 
does is make it easier for the system to not make a change unless needed and 
significantly speed up the updating of the status bar.  This is especially 
useful for the Timer procedure because in many cases, it will be a quick in 
and out process.  As such, if you make a change, just update the panel you 
want.  In most cases, you will want to update only the text panel as you will 
probably use that to display feedback to your user.


There are no VBX's or DLL's used except for the DrawText, GetKeyState and 
BitBlt API functions.  That's all that's needed.  The rest is done all through 
VB code. 


Use of the Status Bar with Menu's and Mouse Movements.
-------------------------------------------------

I purposely did not include examples of how to use menu events to update the 
Status Bar.  You are probably going to need a VBX that intercepts Window's 
messages.  As far as mouse movements are concerned, you add those to wherever 
you wish by simple calling the UpdateTextPanel procedure and pass the 
StatusBar control, the Panel element from the array, and the new caption.  
In this case, there is enough flexibility to abstract some of that by calling 
one procedure that makes the decision of which panel gets updated and when 
and then you call one procedure for any changes.  In my usage of this code, I 
usually have the main form have a StatusBar only (such as an MDI form) and then 
modularly declare the status panels in my application's main module.  In that 
module, I have an initialization procedure and a procedure which handles the 
display of the status bar.  Also, I have added pop-up menu support for turning 
on and turning off specific panels by the user.  That info is saved in an INI 
file so if the user wants to add GDI meter and FSR meter and a CapsLock panel, 
they can do it by right clicking the mouse on the StatusBar and having a 
Pop-up menu which turns off or turns on different configurations and even 
changes what the panels actually show.  Some may want to have three SBAR_METER 
panels, a SBAR_FULLDATE panel, the SBAR_CAPSLOCK panel, and two SBAR_MINICON 
panels which monitor printing and incoming mail.   Again, it is easy to add 
procedures which can increase the functionality of your StatusBar and make it 
effective for your application.  While I could have added all that 
functionality, time is something I don't have a lot of.  Suffice it to say, 
this code is not a solution as it is more of a template.

One small not if you allow users to dynamically change or you dynamically 
change the status bar panels configuration - call the DisplayStatusBar 
procedure to redraw the status bar after you change the configuration so you 
don't get a funny looking status bar.  An example would be like you changed 
panel 2 from an SBAR_METER to an SBAR_ICONMIXED format.  Obviously, you are 
going to have to redraw the whole thing again to make it look correct.  Again, 
the DisplayStatusBar procedure will take care of this for you.  A better 
method would be to call the Form_Resize event which automatically redraws the 
status bar.

There is also those who like to use what I call a Flash Message method. What 
this does is redraw the entire status bar and displays just a message.  To use 
the FlashMessage, pass the StatusBar and the message you want to display and 
voila.  At some point, you will need to restore the status bar.  Just call the 
DisplayStatusBar procedure.  Real quick.

I would encourage you to look at the sample project to see how easy it is to 
add functionality.  You can experiment with it to better understand how it 
works and really get a sense of how well this can work in your application.

VB 4.0
-------------------------------------------------

VB 4.0 may make this obsolete so I don't think I will do anymore with this 
code.  However, if they do something and it turns out that it can't do what 
this code can do.. guess what.. I will make it VB 4.0 compatible..<g>


Disclaimer
-------------------------------------------------

I hate to do this but the reason is very simple.  This code is for you to use 
for FREE.  You may modify it in whatever manner you choose.  I am more 
interested in helping those who are looking for something with some good 
functionality, but can be tailored to fit a specific need.  Because of this:

I MAKE NO WARRANTY EITHER EXPRESSED OR IMPLIED ON THE RELIABILITY OR 
USEFULNESS OF THIS PRODUCT.  I ASSUME NO LIABILITY OR RESPONSIBILITY FOR ANY 
DAMAGES CAUSED BY USE OF THIS PRODUCT.  THE USER ASSUMES ALL RISK FOR USE OF 
THIS PRODUCT.

If you have any questions or comments, and especially if you have suggestions 
or things to add to it, you are encouraged to make contact with me.  I am very 
interested to see what types of changes you make or improvements you add.  I 
would very much like a copy of what you did.  I never claim nor do I ever try 
to imply that I know everything, but I like to share information and if you 
have some stuff for me, I would certainly love the opportunity to share code 
or say hello.

Good Luck and Enjoy!

M. John Rodriguez



