Status bar stuff

by Mark G. Wiseman

Most of the programs I write use status bars. I normally just use the TStatusBar component in the VCL. TStatusBar does just about everything I want. The one irritation I have with TStatusBar is the fact that it aligns the panels within the status bar to the left (Figure A). I don’t like this. I want the panels aligned to the right (Figure B).

 

Figure A: Status bar panels aligned to left. Bad!

 

IMG00011.gif

 

Figure B: Status bar panels aligned to right. Good!

 

IMG00012.gif

 

I am going to show you how I align the panels to the right and how I keep them aligned that way when the form that contains the status bar is resized. While I’m at it, I’m going to show you a few other things you can do with TStatusBar.

There is an example program that accompanies this article. You can find it at the Bridges Publishing Web site.

 

Right-aligned panels

I placed a TStatusBar component on a form named TStatusBarForm. TStatusBar has an event named OnResize that will fire whenever the TStatusBar is resized. I assigned the following code to the OnResize event: 

int width = 0;

for (int i = 1; i < 
     StatusBar->Panels->Count; i++)
  width += StatusBar->Panels->Items[i]->Width;

StatusBar->Panels->Items[0]->Width = 
  StatusBar->ClientWidth - width;

This code will align the panes to the right in the status bar. It does this by assigning, to the left-most panel, a width that will push the rest of the panels all the way to the right.

TStatusBar contains a property, Panels. Panels contains a list of the panels in the status bar. The list is contained in the Items property of Panels as a zero-based array. The first or left-most panel is Item[0]. The code sums the width of all the panels except the first panel. It then subtracts this sum from the ClientWidth of the TStatusBar and assigns the result to the first panel.

It is important to use the ClientWidth property of TStatusBar and not the Width property. The Width property includes the border width of TStatusBar and would make the first panel too wide.

The OnResize event of TStatusBar is fired every time the status bar is resized, including when the status bar is first created.

 

Owner-drawn panels

If you want to put anything other than text into a TStatusBar panel, you will need to use owner-drawn panels. This is actually very easy to do.

In the Object Inspector for TStatusBar, click on the button for the Panels property to bring up the panels editor. Click on one of the panels to show its properties in the Object Inspector. Next change the Style property of the panel from psText to psOwnerDraw.

Now, go back to the Object Inspector for TStatusBar. Under the Events tab, double click on the OnDrawPanel event to insert the skeleton code for the event into your form. Now all you have to do is add the code to draw your panel.

In the example program, I draw a colored rectangle in one panel. The rectangle is either red or green based on the state of a TCheckBox component. Here is the code to do that:

void __fastcall 
TStatusBarForm::StatusBarDrawPanel(
  TStatusBar *StatusBar, 
  TStatusPanel *Panel, 
  const TRect &Rect)
{
  StatusBar->Canvas->Brush->Color = 
    WarningChk->Checked ? 
      clRed : clGreen;
  StatusBar->Canvas->FillRect(Rect);
}

As you can see, I only wrote two lines of code; the rest was generated by the IDE.

 

Other stuff

There are a few more things I wanted to tell you about TStatusBar. If you set the AutoHint property to true, hints will be automatically displayed in the first panel of the status bar. You don’t need to write any code to display hints!

If you set the SimplePanel property to true, the status bar will display only the first panel. If you have created other panels, they will be hidden. This might be useful if you want to display a very long hint. When SimplePanel is true, you can set the text displayed in the Panel by assigning a string to the SimpleText property.

Finally, the SizeGrip property of TStatusBar controls the display of the size grip at the bottom right corner of the status bar. Setting this property to false will cause the grip to be hidden.