• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 772
  • Last Modified:

Auto size the panels of the statusbar

Hello everybody,

Is it possible to auto size the statusbar panels?

So that the width of the panel sadjust to the text in the panel.

This is what i made when the user resizes the form
now i need help with the auto size the panels.

procedure TMainForm.StatusBar2Resize(Sender: TObject);
begin
    with StatusBar2 do
    Panels[0].Width := Width - Panels[1].Width -
    Panels[2].Width - Panels[3].Width - Panels[4].Width -
    Panels[5].Width - Panels[6].Width
end;
(*-----------------------------------------------*)
procedure TMainForm.StatusBar1Resize(Sender: TObject);
begin
  with StatusBar1 do
  Panels[0].Width := Width - Panels[1].Width -
  Panels[2].Width - Panels[3].Width - Panels[4].Width;
end;
(*-----------------------------------------------*)

Kind Regards,

Peter Kiers
0
peterkiers
Asked:
peterkiers
  • 7
  • 5
1 Solution
 
peterkiersAuthor Commented:
I have searched and found this:

procedure AutoSizeStatusbarPanel(sb: TStatusBar; idx:Integer);
var
   s : string;
   borders : array[0..2] of Integer;
begin
   // don't deal with simple panels
   if sb.SimplePanel
      // don't resize the last panel
      or (idx >= sb.Panels.Count-1) then
      Exit;

   // get the borders of the statusbar
   // border[0] = width of the horizontal border
   // border[1] = width of the vertical border
   // border[2] = width of the border between rectangles
   SendMessage(sb.Handle, SB_GETBORDERS, 0, Integer(@borders));

   s := sb.Panels[idx].Text;

   // calculate the width of the Panel
   sb.Panels[idx].Width := TrueFontWidth(sb.Font, s) +
      borders[2]*2 +2; // vertical border * 2 + 2 extra Pixels
end;

function TrueFontWidth(fnt: TFont; const text:string): Integer;
var
   dc: hdc;
   tsize : Windows.TSize;
begin
   dc := GetDC(0);
   SelectObject(DC, fnt.Handle);
   GetTextExtentPoint32(dc, PChar(text), Length(text), tsize);
   ReleaseDC(0, DC);
   Result := tsize.cx;
end;

But I have no idea what the procedure
and the function means!

P.
0
 
peterkiersAuthor Commented:
After running it i get:

[Error] Main.pas(3029): Undeclared identifier: 'SB_GETBORDERS'
0
 
Russell LibbySoftware Engineer, Advisory Commented:
Seems like the AutoSizeStatusbarPanel(sb: TStatusBar; idx:Integer);
procedure wants a status bar control and the index of the panel to autosize. Also, include the CommCtrl unit in your uses clause to fix the reference error

Regards,
Russell

0
Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

 
peterkiersAuthor Commented:
Oke, i have this:

procedure TMainForm.AutoSizeStatusbarPanel(Statusbar1: TStatusBar;
  idx: Integer);
var
   s : string;
   borders : array[0..2] of Integer;
begin
   // don't deal with simple panels
   if Statusbar2.SimplePanel
      // don't resize the last panel
      or (idx >= Statusbar1.Panels.Count-1) then
      Exit;

   // get the borders of the statusbar
   // border[0] = width of the horizontal border
   // border[1] = width of the vertical border
   // border[2] = width of the border between rectangles
   SendMessage(Statusbar2.Handle, SB_GETBORDERS, 0, Integer(@borders));

   s := Statusbar2.Panels[idx].Text;

   // calculate the width of the Panel
   Statusbar1.Panels[idx].Width := TrueFontWidth(Statusbar2.Font, s) +
      borders[2]*2 +2; // vertical border * 2 + 2 extra Pixels
end;

Now my application execute, but the procedure doesn't work?

Peter
0
 
peterkiersAuthor Commented:
And I have this message:

[Hint] Main.pas(372): Private symbol 'AutoSizeStatusbarPanel' declared but never used
0
 
Russell LibbySoftware Engineer, Advisory Commented:

Um, not sure why you are mixing statusbar2 and statusbar1 in the same calls?. Perhaps this will clarify it a little bit. Example form code first, dfm follows

Russell

--
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  CommCtrl, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    StatusBar1: TStatusBar;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

function   TrueFontWidth(fnt: TFont; const text:string): Integer;
procedure  AutoSizeStatusbarPanel(sb: TStatusBar; idx:Integer);

var
  Form1: TForm1;

implementation
{$R *.DFM}

procedure AutoSizeStatusbarPanel(sb: TStatusBar; idx:Integer);
var
   s : string;
   borders : array[0..2] of Integer;
begin
   // don't deal with simple panels
   if sb.SimplePanel
      // don't resize the last panel
      or (idx >= sb.Panels.Count-1) then
      Exit;

   // get the borders of the statusbar
   // border[0] = width of the horizontal border
   // border[1] = width of the vertical border
   // border[2] = width of the border between rectangles
   SendMessage(sb.Handle, SB_GETBORDERS, 0, Integer(@borders));

   s := sb.Panels[idx].Text;

   // calculate the width of the Panel
   sb.Panels[idx].Width := TrueFontWidth(sb.Font, s) +
      borders[2]*2 +2; // vertical border * 2 + 2 extra Pixels
end;

function TrueFontWidth(fnt: TFont; const text:string): Integer;
var
   dc: hdc;
   tsize : Windows.TSize;
begin
   dc := GetDC(0);
   SelectObject(DC, fnt.Handle);
   GetTextExtentPoint32(dc, PChar(text), Length(text), tsize);
   ReleaseDC(0, DC);
   Result := tsize.cx;
end;

procedure TForm1.Button1Click(Sender: TObject);
var  dwIndex:    Integer;
begin

  for dwIndex:=0 to Pred(StatusBar1.Panels.Count) do
     AutoSizeStatusbarPanel(StatusBar1, dwIndex);

end;

end.

--- dfm ---
object Form1: TForm1
  Left = 216
  Top = 120
  Width = 535
  Height = 197
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object StatusBar1: TStatusBar
    Left = 0
    Top = 144
    Width = 527
    Height = 19
    Panels = <
      item
        Text = 'Hello world this is a test'
        Width = 50
      end
      item
        Text = '100'
        Width = 50
      end
      item
        Text = 'Some other very long text'
        Width = 50
      end
      item
        Text = 'Delphi'
        Width = 50
      end>
    SimplePanel = False
  end
  object Button1: TButton
    Left = 16
    Top = 12
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 1
    OnClick = Button1Click
  end
end

0
 
peterkiersAuthor Commented:
Hi,

Thank you for the example, your example works fine.
But not in my application, and I think the problem is
that i dont have to autosize all the panels.

I have 7 panels (0 to 6) and I want only panel 1,3  and 5
to autosize.

Peter
0
 
Russell LibbySoftware Engineer, Advisory Commented:
???? Then use

  AutoSizeStatusbarPanel(StatusBar1, 1);
  AutoSizeStatusbarPanel(StatusBar1, 3);
  AutoSizeStatusbarPanel(StatusBar1, 5);

My code was a demo of usage only. If you want to autosize only 1 panel, then pass the owning statusbar and the panel index. If you want to do it for 3 panels, then call the function 3 times. if you need to do it for another status bar, then pass that status bar in.

  AutoSizeStatusbarPanel(StatusBar2, 1);

If you are having trouble then please post the code you have.

Russell

0
 
peterkiersAuthor Commented:
I try and I try, but no luck sofar...

procedure TMainForm.FormCreate(Sender: TObject);
var
  dwIndex:    Integer;
begin
  AutoSizeStatusbarPanel(StatusBar2, 1);
  AutoSizeStatusbarPanel(StatusBar2, 3);
  AutoSizeStatusbarPanel(StatusBar2, 5);
end;
(*-----------------------------------------------*)
procedure TMainForm.AutoSizeStatusbarPanel(sb: TStatusBar; idx: Integer);
var
   s : string;
   borders : array[0..2] of Integer;
begin
   // don't deal with simple panels
   if sb.SimplePanel
      // don't resize the last panel
      or (idx >= sb.Panels.Count-1) then
      Exit;

   // get the borders of the statusbar
   // border[0] = width of the horizontal border
   // border[1] = width of the vertical border
   // border[2] = width of the border between rectangles
   SendMessage(sb.Handle, SB_GETBORDERS, 0, Integer(@borders));

   s := sb.Panels[idx].Text;

   // calculate the width of the Panel
   sb.Panels[idx].Width := TrueFontWidth(sb.Font, s) +
      borders[2]*2 +2; // vertical border * 2 + 2 extra Pixels
end;
(*-----------------------------------------------*)
function TMainForm.TrueFontWidth(fnt: TFont; const text: string): Integer;
var
   dc: hdc;
   tsize : Windows.TSize;
begin
   dc := GetDC(0);
   SelectObject(DC, fnt.Handle);
   GetTextExtentPoint32(dc, PChar(text), Length(text), tsize);
   ReleaseDC(0, DC);
   Result := tsize.cx;
end;
(*-----------------------------------------------*)
procedure TMainForm.StatusBar2Resize(Sender: TObject);
begin
  with StatusBar2 do
  Panels[0].Width := Width - Panels[1].Width -
  Panels[2].Width - Panels[3].Width - Panels[4].Width -
  Panels[5].Width - Panels[6].Width;
end;
(*-----------------------------------------------*)

Peter
0
 
Russell LibbySoftware Engineer, Advisory Commented:
Get rid of the handling in the form create, and change your StatusBar2Resize logic to this:

procedure TMainForm.StatusBar2Resize(Sender: TObject);
begin

  AutoSizeStatusbarPanel(StatusBar2, 1);
  AutoSizeStatusbarPanel(StatusBar2, 3);
  AutoSizeStatusbarPanel(StatusBar2, 5);
  with StatusBar2 do
     Panels[0].Width:=Width - Panels[1].Width - Panels[2].Width - Panels[3].Width - Panels[4].Width - Panels[5].Width - Panels[6].Width;

end;

The above worked fine for me, as it kept panels 1 3 and 5 to the proper size. Now, if you are setting a panel's text somewhere in code, you need to remebemer to Autosize the panel after the text has been set, eg:

 StatusBar2.Panels[1].Text:='Some new text';
 AutoSizeStatusbarPanel(StatusBar2, 1);

---

Russell



0
 
peterkiersAuthor Commented:
It works perfectly.

Thank you.

500 point comming your way...

Bye.

P.
0
 
Russell LibbySoftware Engineer, Advisory Commented:

And thank you Peter..

Russell
0

Featured Post

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

  • 7
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now