abulka
asked on
Panel component which resizes children
This simple descendent of a TPanel component resizes children controls at DESIGN time. It works OK, except it has a bug where if you close the project, then reopen the project, THEN resize one of the stretchPanels, the children controls of that panel resize themselves wildly. After that, it works ok. It also works ok if you drop a 'stretchPanel' component on a form from scratch and drop some controls inside it.
I need to know what is going wrong and why!
Here is the component source:
unit aPanel1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls;
type
TPanelStretch = class(TPanel)
private
{ Private declarations }
nOldWidth, nOldHeight: integer;
protected
{ Protected declarations }
procedure Resize; override;
public
{ Public declarations }
constructor create(AOwner : TComponent); override;
// procedure Resize(const Value: TNotifyEvent); override;
published
{ Published declarations }
// property OnResize: TNotifyEvent read aaResize write aaResize; override;
// property OnResize; override;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Sample s', [TPanelStretch]);
end;
{ TPanel1 }
constructor TPanelStretch.Create(AOwne r: TComponent);
begin
inherited Create(AOwner);
if ( csDesigning in ComponentState ) then
begin
nOldWidth := Width;
nOldHeight := Height;
end
else
begin
nOldWidth := -1;
nOldHeight := -1;
end;
end;
procedure TPanelStretch.Resize;
var
i: Integer;
ratio: Double;
ctl: TWinControl;
begin
inherited;
if ( nOldWidth = -1 ) and ( nOldHeight = -1 ) then
begin
nOldWidth := Width;
nOldHeight := Height;
exit;
end;
ratio := Width / nOldWidth;
for i := 0 to ControlCount - 1 do
begin
ctl := TWinControl( Controls[i] );
ctl.Left := Round( ctl.Left * ratio );
ctl.Width := Round( ctl.Width * ratio );
end;
ratio := Height / nOldHeight;
for i := 0 to ControlCount - 1 do
begin
ctl := TWinControl( Controls[i] );
ctl.Top := Round( ctl.Top * ratio );
ctl.Height := Round( ctl.Height * ratio );
end;
nOldWidth := Width;
nOldHeight := Height;
end;
end.
I need to know what is going wrong and why!
Here is the component source:
unit aPanel1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls;
type
TPanelStretch = class(TPanel)
private
{ Private declarations }
nOldWidth, nOldHeight: integer;
protected
{ Protected declarations }
procedure Resize; override;
public
{ Public declarations }
constructor create(AOwner : TComponent); override;
// procedure Resize(const Value: TNotifyEvent); override;
published
{ Published declarations }
// property OnResize: TNotifyEvent read aaResize write aaResize; override;
// property OnResize; override;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Sample
end;
{ TPanel1 }
constructor TPanelStretch.Create(AOwne
begin
inherited Create(AOwner);
if ( csDesigning in ComponentState ) then
begin
nOldWidth := Width;
nOldHeight := Height;
end
else
begin
nOldWidth := -1;
nOldHeight := -1;
end;
end;
procedure TPanelStretch.Resize;
var
i: Integer;
ratio: Double;
ctl: TWinControl;
begin
inherited;
if ( nOldWidth = -1 ) and ( nOldHeight = -1 ) then
begin
nOldWidth := Width;
nOldHeight := Height;
exit;
end;
ratio := Width / nOldWidth;
for i := 0 to ControlCount - 1 do
begin
ctl := TWinControl( Controls[i] );
ctl.Left := Round( ctl.Left * ratio );
ctl.Width := Round( ctl.Width * ratio );
end;
ratio := Height / nOldHeight;
for i := 0 to ControlCount - 1 do
begin
ctl := TWinControl( Controls[i] );
ctl.Top := Round( ctl.Top * ratio );
ctl.Height := Round( ctl.Height * ratio );
end;
nOldWidth := Width;
nOldHeight := Height;
end;
end.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Sounds good. Can you give me a template line or two of code for overriding the Loaded method?
Viz. When I overrode the resize method, I was faced with options to override e.g. the resize property and possibly the resize notification events? and I got lost inside the VCL source code trying to find the right thing to override (and and syntax)
Viz. When I overrode the resize method, I was faced with options to override e.g. the resize property and possibly the resize notification events? and I got lost inside the VCL source code trying to find the right thing to override (and and syntax)
procedure Loaded;override;
procedure TPanelStretch.Loaded;
begin
Inherited;
OldWidth := Width;
OldHeight := Height;
end;
Cheers,
Viktor
procedure TPanelStretch.Loaded;
begin
Inherited;
OldWidth := Width;
OldHeight := Height;
end;
Cheers,
Viktor
Viktor has done it nicely...
Cheers,
Raymond.
Cheers,
Raymond.
ASKER
Thanks. Here is the finished component. Pretty clean and simple.
unit aPanel1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls;
type
TPanelStretch = class(TPanel)
private
{ Private declarations }
nOldWidth, nOldHeight: integer;
protected
{ Protected declarations }
procedure Resize; override;
procedure Loaded; override;
public
{ Public declarations }
constructor create(AOwner : TComponent); override;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Sample s', [TPanelStretch]);
end;
{ TPanel1 }
constructor TPanelStretch.Create(AOwne r: TComponent);
begin
inherited Create(AOwner);
nOldWidth := Width;
nOldHeight := Height;
end;
procedure TPanelStretch.Loaded;
begin
inherited;
nOldWidth := Width;
nOldHeight := Height;
end;
procedure TPanelStretch.Resize;
var
i: Integer;
ratio: Double;
ctl: TWinControl;
begin
inherited;
ratio := Width / nOldWidth;
for i := 0 to ControlCount - 1 do
begin
ctl := TWinControl( Controls[i] );
ctl.Left := Round( ctl.Left * ratio );
ctl.Width := Round( ctl.Width * ratio );
end;
ratio := Height / nOldHeight;
for i := 0 to ControlCount - 1 do
begin
ctl := TWinControl( Controls[i] );
ctl.Top := Round( ctl.Top * ratio );
ctl.Height := Round( ctl.Height * ratio );
end;
nOldWidth := Width;
nOldHeight := Height;
end;
end.
unit aPanel1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls;
type
TPanelStretch = class(TPanel)
private
{ Private declarations }
nOldWidth, nOldHeight: integer;
protected
{ Protected declarations }
procedure Resize; override;
procedure Loaded; override;
public
{ Public declarations }
constructor create(AOwner : TComponent); override;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Sample
end;
{ TPanel1 }
constructor TPanelStretch.Create(AOwne
begin
inherited Create(AOwner);
nOldWidth := Width;
nOldHeight := Height;
end;
procedure TPanelStretch.Loaded;
begin
inherited;
nOldWidth := Width;
nOldHeight := Height;
end;
procedure TPanelStretch.Resize;
var
i: Integer;
ratio: Double;
ctl: TWinControl;
begin
inherited;
ratio := Width / nOldWidth;
for i := 0 to ControlCount - 1 do
begin
ctl := TWinControl( Controls[i] );
ctl.Left := Round( ctl.Left * ratio );
ctl.Width := Round( ctl.Width * ratio );
end;
ratio := Height / nOldHeight;
for i := 0 to ControlCount - 1 do
begin
ctl := TWinControl( Controls[i] );
ctl.Top := Round( ctl.Top * ratio );
ctl.Height := Round( ctl.Height * ratio );
end;
nOldWidth := Width;
nOldHeight := Height;
end;
end.
Maybe when the project is loaded the OldWidth and Height are set to 0 or something and then when you resize it it resizes wildly :)
Cheers,
Viktor