Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Auto size the panels of the statusbar

Posted on 2006-07-19
12
Medium Priority
?
753 Views
Last Modified: 2010-04-05
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
Comment
Question by:peterkiers
  • 7
  • 5
12 Comments
 
LVL 1

Author Comment

by:peterkiers
ID: 17138484
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
 
LVL 1

Author Comment

by:peterkiers
ID: 17138746
After running it i get:

[Error] Main.pas(3029): Undeclared identifier: 'SB_GETBORDERS'
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17138974
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Author Comment

by:peterkiers
ID: 17139074
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
 
LVL 1

Author Comment

by:peterkiers
ID: 17139124
And I have this message:

[Hint] Main.pas(372): Private symbol 'AutoSizeStatusbarPanel' declared but never used
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17139143

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
 
LVL 1

Author Comment

by:peterkiers
ID: 17139460
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
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17139528
???? 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
 
LVL 1

Author Comment

by:peterkiers
ID: 17139620
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
 
LVL 26

Accepted Solution

by:
Russell Libby earned 2000 total points
ID: 17139731
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
 
LVL 1

Author Comment

by:peterkiers
ID: 17140158
It works perfectly.

Thank you.

500 point comming your way...

Bye.

P.
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17140191

And thank you Peter..

Russell
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
With just a little bit of  SQL and VBA, many doors open to cool things like synchronize a list box to display data relevant to other information on a form.  If you have never written code or looked at an SQL statement before, no problem! ...  give i…
Suggested Courses

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question