Solved

Auto size the panels of the statusbar, part 2

Posted on 2006-07-20
9
1,395 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
Comment Utility
>> 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
Comment Utility
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
Comment Utility
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
 
LVL 1

Author Comment

by:peterkiers
Comment Utility
The panels to crop good be Panel 2 and 4.

p.

 
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 26

Expert Comment

by:Russell Libby
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
It works.

Thank you, another 500 point comming your way.

Peter
0
 
LVL 26

Expert Comment

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

Russell
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

743 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now