tags:

views:

75

answers:

2

I have a "wide" TPanel with several buttons on it (essentially a tool bar). All the buttons have Align=Left. I have created a function which will resize the buttons to the same size and calculate the width of them so they fill the entire TPanel. I call this function in the OnResize event handler of the TPanel.

procedure ScaleButtonsOnPanel;
var i: Integer;
begin
  for i:=0 to mPanel.ControlCount-1 do begin
      mPanel.Controls[i].Width := round(mPanel.width/mPanel.ControlCount-1)
  end;
end;

The problem is if I minimize and then restore the form the layout of the buttons change from the design layout.

Can anyone offer a solution to having buttons on a panel which can be resized but maintain the design time order (in terms of left to right placement) ?

+2  A: 

I do not really see your problem. But of course, you must set the position of the buttons, not only their size.

procedure TForm1.Panel1Resize(Sender: TObject);
var
  i: Integer;
  btnWidth: integer;
begin
  btnWidth := Panel1.Width div Panel1.ControlCount;
  for i := 0 to Panel1.ControlCount - 1 do
  begin
    Panel1.Controls[i].Left := i * btnWidth;
    Panel1.Controls[i].Width := btnWidth;
  end;
end;

This works very well.

See http://privat.rejbrand.se/panelresize.wmv.

OK, now I see. I think the alLeft is actually your problem. Controls with the same align tend to change their order. This is a well-known Delphi annoyance. Do it like I do above, instead. Just make sure that you go through the buttons in the right order. If you cannot rely on the ordering of Panel1.Controls, then you can do like this: Set the Tag property of each toolbar button to its position (0, 1, ...) in the toolbar then do

procedure TForm1.Panel1Resize(Sender: TObject);
var
  i: Integer;
  btnWidth: integer;
begin
  btnWidth := Panel1.Width div Panel1.ControlCount;
  for i := 0 to Panel1.ControlCount - 1 do
  begin
    Panel1.Controls[i].Left := Panel1.Controls[i].Tag * btnWidth;
    Panel1.Controls[i].Width := btnWidth;
  end;
end;
Andreas Rejbrand
That was the purpose of the "Align=Left", so we didn't need to worry about setting the position. They would just "fall into place". When you loop over the controls can you be assured they go "left to right"?
M Schenkel
OK. I see. But what in the world is the problem, then? :)
Andreas Rejbrand
OK, now I see. I think the `alLeft` *is* actually your problem. Controls with the same align tend to change their order. This is a well-known Delphi annoyance. Do it like I do above, instead.
Andreas Rejbrand
I will give this a try. But I do have a "side" question: when looping over the controls it assumes the control with index 0 is the left most control, that associated with 1 is to the right of control index on 0. Is this a valid assumption? Or is it arbitrary?
M Schenkel
@M Schenkel: No, use tags instead! See my updated answer.
Andreas Rejbrand
I see - you are using the "Tag" property to deal with this. But is there anyway not to rely on the "Tag" property? This would cause double work for the developer. We like to just use the align property during design to establish the order. I guess I would have to write a pre-processor function which gets called before anything to find out the layout order.
M Schenkel
sorry - was composing my comment when you wrote yours!!!!
M Schenkel
+2  A: 

Have you tried to see if a TFlowPanel doesn't better suit your needs?

François
I will have to check that out.
M Schenkel