Solved

Auto size the panels of the statusbar, part 2

Posted on 2006-07-20
9
1,449 Views
Last Modified: 2010-04-05
Hi, Experts,

Yesterday, i have asked a question how to auto size the panels of the statusbar.
I have received a good solution from rlibby, but after closing the question,  I found
out the solution i received brings another problem.

My statusbar has 7 panels, and only panel 1,3 and 5 is used to display some text.
And the solutions from rlibby is good, only if text appear in panel1, panel3 and 5
moves to the right.

Is there a way to lock a panel?

This is the code I have received yersterday:

  private
    { Private declarations }
    function  TrueFontWidth(fnt: TFont; const text:string): Integer;
    procedure AutoSizeStatusbarPanel(sb: TStatusBar; idx:Integer);

  (*-----------------------------------------------*)
procedure TMainForm.AutoSizeStatusbarPanel(sb: TStatusBar; idx: Integer);
var
   s : string;
   borders : array[0..2] of Integer;
begin
   if sb.SimplePanel
      or (idx >= sb.Panels.Count-1) then
      Exit;
   SendMessage(sb.Handle, SB_GETBORDERS, 0, Integer(@borders));
   s := sb.Panels[idx].Text;
   sb.Panels[idx].Width := TrueFontWidth(sb.Font, s) +
      borders[2]*2 +2;
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
    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;
(*-----------------------------------------------*)

Can someone PLEASE help me?

Peter Kiers
0
Comment
Question by:peterkiers
  • 5
  • 4
9 Comments
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17146032
>> And the solutions from rlibby is good, only if text appear in panel1, panel3 and 5
moves to the right.

You wanted the panels (1,3,5 in this case) to autosize to the actual width of the text in the panel, which IS what you got. Can you explain further what you mean by locking a panel? (what is the desired effect, what is the current effect, and a small example with code / dfm would be useful)

Russell
0
 
LVL 1

Author Comment

by:peterkiers
ID: 17146249
My statusbar has 7 panels. After pressing F9, this text appears in panel 5:

Row 01 / Column 01

This text appears in panel 3 after the user presses the Insert-key:

INS

This text appears in panel 1 after the user presses the return-key:

KEYBOARD LOCKED

So, when the user presses the return-key, the text KEYBOARD LOCKED is being displayed
(so the panel is getting larger) but also moves the panels right from it to the right.
so I only get to see in panel5 the letters Row instead of Row 01 / Column 01, the rest
is gone(off screen).

Isn't there a way to lock panel5?

Forgive me, my English is very bad, and its hard for me to explain the problem.
 
Peter
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17146500
No, I think I understand what your saying. But let me ask you this.

You have 7 panels, 3 are set to autosize to the width of their actual text contents, and the very first panel (0) is set to give up its width based on total width minus the accumulated size of the other panels. If the status bar width is not large enough to display all 7 panels, then someone (some panel) is not going to get displayed. I think you are asking if there is a way to lock the location of panel 5 (so it does not get shifted right), but that leaves the question of which column(s) to crop?

So simply put, if a panel needs to get cropped, which one is it going to be? And if more need to get cropped. Then which direction do you crop from (do you move them left, or keep them fixed, which crops the right side?)

Russell


0
Independent Software Vendors: 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: 17146573
The panels to crop good be Panel 2 and 4.

p.

 
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17147211
This should be close to what you after, it gives up panel 0 first, panel 2 next and then panel 4 before giving up the rest.
Let me know if there are questions / problems.

Russell

--
unit Unit1;

interface

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

type
  TMainForm         =  class(TForm)
     StatusBar2:    TStatusBar;
     procedure      StatusBar2Resize(Sender: TObject);
     procedure      FormCreate(Sender: TObject);
     procedure      FormKeyPress(Sender: TObject; var Key: Char);
  private
     // Private declarations
     FMinWidth:     Integer;
     FLastWidth:    Integer;
     FMaxWidths:    Array [0..6] of Integer;
     function       TrueFontWidth(fnt: TFont; const text: string): Integer;
     procedure      AutoSizeStatusbarPanel(sb: TStatusBar; idx: Integer);
  public
     // Public declarations
  end;

var
  MainForm:         TMainForm;

implementation
{$R *.DFM}

procedure TMainForm.AutoSizeStatusbarPanel(sb: TStatusBar; idx: Integer);
var
   s : string;
   borders : array [0..2] of Integer;
begin
   if sb.SimplePanel
      or (idx >= sb.Panels.Count-1) then
      Exit;
   SendMessage(sb.Handle, SB_GETBORDERS, 0, Integer(@borders));
   s := sb.Panels[idx].Text;
   sb.Panels[idx].Width := TrueFontWidth(sb.Font, s) + FMinWidth;
end;
(*-----------------------------------------------*)
function TMainForm.TrueFontWidth(fnt: TFont; const text: string): Integer;
var  DC:            HDC;
     tsize :        Windows.TSize;
begin
  DC:=GetDC(0);
  try
     SelectObject(DC, fnt.Handle);
     GetTextExtentPoint32(dc, PChar(text), Length(text), tsize);
     Result:=tsize.cx;
  finally
     ReleaseDC(0, DC);
  end;
end;

procedure TMainForm.StatusBar2Resize(Sender: TObject);
var  dwWidth:       Integer;
     dwIndex:       Integer;
begin

  // Make sure the autosize panels are updated
  AutoSizeStatusbarPanel(StatusBar2, 1);
  AutoSizeStatusbarPanel(StatusBar2, 3);
  AutoSizeStatusbarPanel(StatusBar2, 5);

  // Update the max widths by including the autosize panel widths
  FMaxWidths[1]:=StatusBar2.Panels[1].Width;
  FMaxWidths[3]:=StatusBar2.Panels[3].Width;
  FMaxWidths[5]:=StatusBar2.Panels[5].Width;

  // Get total display width
  dwWidth:=StatusBar2.Width;

  // Subtract the autosize widths from the total width
  Dec(dwWidth, FMaxWidths[1] + FMaxWidths[3] + FMaxWidths[5]);

  // Shorthand status bar
  with StatusBar2 do
  begin
     // Check remaining width
     if (dwWidth < (FMinWidth * 2 + 2)) then
     begin
        // There is not enough room to display the autosize panels, let alone any other panels
        Panels[2].Width:=FMinWidth;
        Panels[4].Width:=FMinWidth;
        Panels[6].Width:=FLastWidth;
     end
     else
     begin
        // Give panel 6 first shot at remaining space
        if (dwWidth > FMaxWidths[6]) then
           Panels[6].Width:=FMaxWidths[6]
        else if (dwWidth > FLastWidth) then
           Panels[6].Width:=dwWidth
        else
           Panels[6].Width:=FLastWidth;
        Dec(dwWidth, Panels[6].Width);
        // Panel 4 is next
        if (dwWidth > FMaxWidths[4]) then
           Panels[4].Width:=FMaxWidths[4]
        else if (dwWidth > FMinWidth) then
           Panels[4].Width:=dwWidth
        else
           Panels[4].Width:=FMinWidth;
        Dec(dwWidth, Panels[4].Width);
        // Panel 2 comes next
        if (dwWidth > FMaxWidths[2]) then
           Panels[2].Width:=FMaxWidths[2]
        else if (dwWidth > FMinWidth) then
           Panels[2].Width:=dwWidth
        else
           Panels[2].Width:=FMinWidth;
        Dec(dwWidth, Panels[2].Width);
     end;
     // Slide panel zero
     Panels[0].Width:=dwWidth;
  end;

end;

procedure TMainForm.FormCreate(Sender: TObject);
var  dwIndex:       Integer;
     dwBorders:     Array [0..2] of Integer;
begin

  // Unbind the OnResize event while we do this
  StatusBar2.OnResize:=nil;

  // Resource protection
  try
     // Save the default widths for the columns (we want to keep the max widths for 2, 4, and 6)
     for dwIndex:=0 to Pred(StatusBar2.Panels.Count) do FMaxWidths[dwIndex]:=StatusBar2.Panels[dwIndex].Width;
     // Save default min width
     SendMessage(StatusBar2.Handle, SB_GETBORDERS, 0, Integer(@dwBorders));
     FMinWidth:=(dwBorders[2] * 2 + 2);
     // Save last panel width (so we don't mess up any gripper)
     FLastWidth:=StatusBar2.Panels[Pred(StatusBar2.Panels.Count)].Width;
     if (FLastWidth > (FMinWidth + 16)) then FLastWidth:=FMinWidth + 12;
  finally
     // Rebind the event
     StatusBar2.OnResize:=StatusBar2Resize;
  end;

  // Update
  StatusBar2Resize(StatusBar2);

end;

procedure TMainForm.FormKeyPress(Sender: TObject; var Key: Char);
begin

  if (Key = #13) then
  begin
     Key:=#0;
     if (StatusBar2.Panels[1].Text = '') then
        StatusBar2.Panels[1].Text:='KEYBOARD LOCKED'
     else
        StatusBar2.Panels[1].Text:='';
     AutoSizeStatusbarPanel(StatusBar2, 1);
     StatusBar2Resize(StatusBar2);
  end;

end;

end.

0
 
LVL 1

Author Comment

by:peterkiers
ID: 17147313
It's still the same.

Isn't much easier for you to send my application to you.

Peter
0
 
LVL 26

Accepted Solution

by:
Russell Libby earned 500 total points
ID: 17147991
Its not the same, but I should have mentioned that when setting the text, you dont need to call AutoSizeStatusbarPanel, but you now need to call StatusBar2Resize.

eg

    if (StatusBar2.Panels[1].Text = '') then
        StatusBar2.Panels[1].Text:='KEYBOARD LOCKED'
     else
        StatusBar2.Panels[1].Text:='';
     // This need to be called after changing any of the text in the panels
     StatusBar2Resize(StatusBar2);
 
Russell

0
 
LVL 1

Author Comment

by:peterkiers
ID: 17148263
It works.

Thank you, another 500 point comming your way.

Peter
0
 
LVL 26

Expert Comment

by:Russell Libby
ID: 17148335
Please let me know if you have any issues with it, and thanks ;-)

Russell
0

Featured Post

Industry Leaders: 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!

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Strange behavior when a form is closed 6 68
Downloading email attachments 2 83
How to renew a Delphi rad-studio licence? 5 75
enhance the following code 3 42
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

713 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