Create a Status Bar using the API

Tuesday Nov 19th 2002 by Sam Huggill

Create a Status Bar using the API

Fed up with distributing the 509KB ComCtl32.ocx with your program just for a single control? In this article, I will take you through creating the common controls using only the Windows API. I will demonstrate how to create a status bar using the CreateStatusWindowA API call. Topics such as adding panels, setting text and a font, getting text and positioning the status bar will be covered.

I first came across this API call in the ComCtrl.h header file. You can't find it in the Windows API viewer (don't know why) but just about all the calls you need can be found in the Windows Header files.

Note: These files are written in C++ syntax and therefore you will need to know the basics of translating this information.

In future articles we will be using the CreateWindowEx call, but for now we can use the CreateStatusWindow call. When we call this function, it returns the the window handle (hWnd) of our new control or 0 if it failed. We can then use this window handle to change the way it looks, and get information about it.

Just a quick note to let you know that all the project files (a form, bas module, project and compiled exe) amount to a mere 4% of the ComCtl32.ocx!

Anyway, lets get on. The constants prefixed by WM_ and WS_ are windows messages and windows styles. The constants prefixed by SB_ are, quite obviously for the status bar. And the constants prefixed by CCS_ relate to the common controls, in this case, the status bar.

We also use a couple of API calls. These include the CreateStatusWindow (already mentioned), SendMessage, DestroyWindow and MoveWindow. The SendMessage, like it sounds, is used for sending messages to our control. The DestroyWindow clears our control from memory and the MoveWindow is self-explanatory.

All of these API calls and constants can be found in the modAPI module, found below.

Option Explicit 
'// NOTE: Some of the constants in this module   
'// wereextracted from the ComCtrl.h header file  

'// API calls needed to create our status bar 
'// through the API  

'// Main API call used to create the window. 
'// Returns the  window handle of the new 
'// status bar  
Public Declare Function CreateStatusWindowA Lib _
   "ComCtl32.dll" _ 
   (ByVal style As Long, _ 
   ByVal lpszText As String, _ 
   ByVal hwndParent As Long, ByVal wID As Long) _
   As Long 
'// Used to change/modify styles in our status bar  
Public Declare Function SendMessage Lib _
   "user32" Alias 
  (ByVal hWnd As Long, _ 
  ByVal wMsg As Long, _ 
  ByVal wParam As Long, lParam As Any) _
  As Long 
'// Used to remove our status bar from memory  
Public Declare Function DestroyWindow Lib _
  "user32" _ 
  (ByVal hWnd As Long) As Long 
'// Move our status bar so we can see it  
Public Declare Function MoveWindow Lib _
  "user32" (ByVal hWnd As Long, _
  ByVal x As Long, ByVal y As Long, ByVal _
  nWidth As Long, ByVal nHeight As Long, _
  ByVal bRepaint As Long) As Long 
'// WM_ Windows Messages and Styles  
Public Const WS_VISIBLE = &H10000000 _
  'Makes it visible  
Public Const WM_USER = &H400 
Public Const WS_CHILD = &H40000000 _
  'Makes it a child of our parent window  
Public Const WM_SIZE = &H5 _
  'Changes the size  
Public Const WM_GETFONT = &H31 _
  'Gets the font from a window  
Public Const WM_SETFONT = &H30 _
  'Sets the font of a window  
'// Status Bar Messages and Styles  
Public Const SB_SETTEXT = (WM_USER + 1) _
  'Sets text  
Public Const sbSimpleIdx = 255 
Public Const SBT_SUNKEN = &H0 _
  'Sunken styles  
Public Const SBT_POPOUT = &H200 _
  'Popped out style  
Public Const SB_GETTEXTLENGTH = (WM_USER + 3) _
  'Returns the text length  
Public Const SB_SETPARTS = (WM_USER + 4) _
  'Adds new panels  
Public Const SB_GETPARTS = (WM_USER + 6) _
  'Retreives panels  
Public Const SB_GETTEXT = (WM_USER + 2) _
  'Returns text  
'// Common Control Styles for alignment  
Public Const CCS_TOP = &H1&  'Top  
Public Const CCS_BOTTOM = &H3&  'Bottom   

Copy and paste that into a new module (or just use the one in the download).

I will take you through the functions found in the form's code. The first, create (found under the command button cmdCreate) is, quite obviously, used to create the status bar. When creating it, we need to apply (as a minimum) the WS_CHILD and WS_VISIBLE constants. These force the status bar to be visible and make it a child of our form. If you omitted the WS_CHILD constants the status bar would draw on the desktop. You might want this, although I doubt your users would! Anyway, after that we use the MoveWindow API call. By default, the status bar assumes its own size/position. A call to the MoveWindow function ensures that we can see our status bar.

The next part, AddCaption (found under cmdAddCaption) changes the text in the status bar. I had some problems using this, mainly getting it to draw text in different panels. You will see what I mean when you use it. Anyway, this uses a small routine to apply new text. We use the SendMessage call to apply the new text using the SB_SETTEXT constant. We also include the style for the panel. I have used the default SBT_SUNKEN style but you could use the SBT_POPOUT (included) or other styles supported.

We now apply a font to the status bar. By using the WM_GETFONT we can get the font of our form (set to Tahoma) and then use the WM_SETFONT and SendMessage to apply the font. If you were wrapping this in an activex control, then you would be getting the font of the usercontrol. You can get the font of any object that has a hWnd property.

Notice in the Form_Resize event I have used the MoveWindow call to resize the status bar. If we didn't do this, then the status bar would just stay the same size both in length and width.

The Add function (found under cmdAdd) basically adds a new panel using the SB_SETPARTS and the SendMessage. First, we have to define the size of this panel and then call the SendMessage function. The destroy function just calls the DestroyWindow with a reference to the status bars window handle.

The form requires six command buttons (although this could be scaled down). Rename them cmdDestroy, cmdCreate, cmdAddCaption, cmdFont, cmdAdd and cmdGetText. Copy and paste the code below into the form:

Option Explicit 
'// Holds the window handle for our status bar  
Private lnghWnd As Long 
Private Sub cmdCreate_Click() 
  Dim lngStyle As Long 
  'WS_CHILD - Makes the status bar a child of  
  'this form.  
  'WS_VISIBLE - Makes the statusbar visible  
  lngStyle = lngStyle Or WS_CHILD 
  lngStyle = lngStyle Or WS_VISIBLE 
  '   Make the statusbar using the 
  '   CreateStatusWindow API Call  
  '   Note: This is much easier than using 
  '   the CreateWindowEx API  
  lnghWnd = CreateStatusWindowA _
   (lngStyle, "VB Square API Drawn _
    Statusbar", Me.hWnd, 0) 
  '   By default, our new status bar assumes
  '   its own position and  
  '   size. Use the MoveWindow API to move it 
  '   to the bottom of the form  
  MoveWindow lnghWnd, 0, ScaleHeight - 20, _
    ScaleWidth, 20, True 
End Sub 
Private Sub cmdAddCaption_Click() 
  Dim strText As String 
  '   Sets the caption for both panels using a   
  '   string from an input box  
  '   For some reason the text doesn't draw  
  '   If anyone knows why, please let me know  
  strText = InputBox$ _
   ("Enter a caption...") 
  SetCaption strText 
End Sub 
Private Sub cmdFont_Click() 
  Dim lRet As Long 
  '   Set the font of the status bar using   
  '   the WM_SETFONT by getting the font from
  '   this form using the WM_GETFONT  
  lRet = SendMessage(Me.hWnd, WM_GETFONT, 0, 0) 
  SendMessage lnghWnd, WM_SETFONT, lRet, 0 
End Sub 
Private Sub cmdAdd_Click() 
  Dim lngParts As Long 
  '   Holds the size of the new panel  
  lngParts = ScaleWidth - 100 
  '   Adds the new panel to our status bar  
  SendMessage lnghWnd, SB_SETPARTS, _
   ByVal 2, lngParts 
End Sub 
Private Sub cmdDestroy_Click() 
  '   Use the DestroyWindow API to destroy 
  '   our status bar  
  DestroyWindow lnghWnd 
  '   Set the window handle holder to 0  
  lnghWnd = 0 
End Sub 
Private Sub cmdGetText_Click() 
  Dim pnlNum As Long 
  '   Find out which panel the user wants 
  '   the text from  
  pnlNum = Val _
   (InputBox("Text from panel number:")) 
  '   Return the text using the GetText function  
  MsgBox GetText(pnlNum) 
End Sub 
Private Sub Form_Load() 
  '   Move the form to the centre of the screen  
  Move (Screen.Width - Width) * 0.5, _
   (Screen.Height - Height) * 0.5 
  '   Set the scalemode to pixels because 
  '   certain functions require this.  
  ScaleMode = vbPixels 
End Sub 
Private Sub Form_Resize() 
  '   Use the WM_SIZE constant to resize the  
  '   status bar to keep it at the bottom 
  '   of the form  
  SendMessage lnghWnd, WM_SIZE, 0, 0 
End Sub 
Function GetPanels() As Integer 
  '   Returns the number of panels  
  GetPanels = SendMessage _
   (lnghWnd, SB_GETPARTS, 0, ByVal 0) 
End Function 
Sub SetCaption(strText As String) 
  Dim lngRet As Long 
  '   Set some new text in the status bar using 
  '   the SM_SETTEXT. Use the SBT_ constants 
  '   to define how the panel looks.  
  lngRet = GetPanels() - 1 
  SendMessage lnghWnd, SB_SETTEXT, _
    ByVal SBT_SUNKEN, ByVal strText 
  SendMessage lnghWnd, SB_SETTEXT, _
    ByVal lngRet Or SBT_SUNKEN, ByVal strText 
End Sub 
Function GetTextLen(pnlNum As Long) As Long 
  Dim lngRet As Long 
  '   Returns the lenght of the string 
  '   in the panel  
  lngRet = SendMessage _
   (lnghWnd, SB_GETTEXTLENGTH, ByVal pnlNum, 0) 
  GetTextLen = (lngRet And &HFFFF&) 
End Function 
Function GetText(pnlNum As Long) As String 
  Dim strText As String 
  Dim lngRet As Long 
  '   Returns the string in the panel 
  '   specificed by pnlNum  
  strText = String$(GetTextLen(pnlNum), 0) 
  lngRet = SendMessage(lnghWnd, SB_GETTEXT, _
   ByVal pnlNum, ByVal strText) 
  GetText = Left$(strText, _
   (lngRet And &HFFFF&)) 
End Function  
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved