Solved

Auto size the panels of the statusbar, part 2

Posted on 2006-07-20
9
1,426 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
Ransomware-A Revenue Bonanza for Service Providers

Ransomware – malware that gets on your customers’ computers, encrypts their data, and extorts a hefty ransom for the decryption keys – is a surging new threat.  The purpose of this eBook is to educate the reader about ransomware attacks.

 
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

VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
proper way to parse text with delphi 7 121
How to fill array with TArray.Create? 14 89
Printing problem 2 91
JAudiorecorder record freezing the app 29 67
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
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…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

776 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