type
TPaneledImage =
class(TImage)
private
FPanel: TPanel;
procedure SetVisible(Value: boolean);
function GetParent: TWinControl;
function GetOwner: TComponent;
reintroduce;
function GetVisible: boolean;
protected
procedure SetParent(AParent: TWinControl);
override;
public
constructor Create(AOwner: TComponent);
override;
destructor Destroy;
override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
override;
property Parent: TWinControl
read GetParent
write SetParent;
property Visible: boolean
read GetVisible
write SetVisible;
property Owner: TComponent
read GetOwner;
end;
constructor TPaneledImage.Create(AOwner: TComponent);
begin
// Host-Panel erstellen
FPanel := TPanel.Create(AOwner);
// Eigenschaften für das Panel
FPanel.BevelOuter := bvNone;
// Das eigentliche Image erstellen
inherited Create(FPanel);
{1}
// inherited Create(AOwner); {2}
// inherited Create(Self); {3}
// Unveränderliche Eigenschaften für das Image im Panel festlegen
inherited SetParent(FPanel);
Align := alClient;
Visible := true;
end;
destructor TPaneledImage.Destroy;
begin
// Zuerst das Panel freigeben. Das Panel wird zuerst Nil gesetzt, dann freigegeben.
// Das Panel wird widerum uns zuerst freigeben, weswegen dieses Destroy ein zweites
// Mal aufgerufen wird und die korrekte Freigabe von TObject einleitet.
if Assigned(FPanel)
then
begin
FreeAndNil(FPanel)
// Diese Zeile wird 1x zuerst aufgerufen
end
else
begin
// Diese Zeile wird 1x danach aufgerufen
inherited;
// Hier wird zusätzlich einmal TPaneledImage.SetParent aufgerufen
end;
// Aber NACH Destroy gibts eine AV!
end;
function TPaneledImage.GetOwner: TComponent;
begin
result := FPanel.Owner;
end;
function TPaneledImage.GetParent: TWinControl;
begin
result := FPanel.Parent;
end;
function TPaneledImage.GetVisible: boolean;
begin
result := FPanel.Visible;
end;
procedure TPaneledImage.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
// Das Image im Panel soll bei (0, 0) bleiben. Nur das Panel bewegt sich.
inherited SetBounds(0, 0, AWidth, AHeight);
FPanel.Left := ALeft;
FPanel.Top := ATop;
FPanel.Width := AWidth;
FPanel.Height := AHeight;
end;
procedure TPaneledImage.SetParent(AParent: TWinControl);
begin
if not Assigned(FPanel)
then exit;
// Verhindern einer AV bei Destroy
if FPanel.Parent <> AParent
then
begin
FPanel.Parent := AParent;
end;
end;
procedure TPaneledImage.SetVisible(Value: boolean);
begin
if FPanel.Visible <> Value
then
begin
FPanel.Visible := Value;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
x: TPaneledImage;
begin
x := TPaneledImage.Create(Self);
try
x.Parent := Self;
x.AutoSize := true;
x.Picture.LoadFromFile('
C:\WINDOWS\Präriewind.BMP');
finally
x.Free;
// Verursacht eine AV, wenn Programm später beendet wird
end;
end;