Solved

Auto size the panels of the statusbar, part 2

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

Author Comment

by:peterkiers
ID: 17146573
The panels to crop good be Panel 2 and 4.

p.

 
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
how do i create updater to My Activex application? 3 79
Best Firemonkey component pack 1 88
how to center only a line in richedit? 4 52
oracle global variables 4 63
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…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, just open a new email message. In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
As a trusted technology advisor to your customers you are likely getting the daily question of, ‘should I put this in the cloud?’ As customer demands for cloud services increases, companies will see a shift from traditional buying patterns to new…

862 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

21 Experts available now in Live!

Get 1:1 Help Now