Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1598
  • Last Modified:

Auto size the panels of the statusbar, part 2

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
peterkiers
Asked:
peterkiers
  • 5
  • 4
1 Solution
 
Russell LibbySoftware Engineer, Advisory Commented:
>> 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
 
peterkiersAuthor Commented:
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
 
Russell LibbySoftware Engineer, Advisory Commented:
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
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.

 
peterkiersAuthor Commented:
The panels to crop good be Panel 2 and 4.

p.

 
0
 
Russell LibbySoftware Engineer, Advisory Commented:
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
 
peterkiersAuthor Commented:
It's still the same.

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

Peter
0
 
Russell LibbySoftware Engineer, Advisory Commented:
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
 
peterkiersAuthor Commented:
It works.

Thank you, another 500 point comming your way.

Peter
0
 
Russell LibbySoftware Engineer, Advisory Commented:
Please let me know if you have any issues with it, and thanks ;-)

Russell
0

Featured Post

[Webinar] Database Backup and Recovery

Does your company store data on premises, off site, in the cloud, or a combination of these? If you answered “yes”, you need a data backup recovery plan that fits each and every platform. Watch now as as Percona teaches us how to build agile data backup recovery plan.

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