Frage

Ist es möglich, zum Beispiel ersetzen und eine TEdit mit einer Unterklasse Komponente frei zur Laufzeit instanziiert (bedingt)? Wenn ja, wie und wann es getan werden sollte? Ich habe versucht, die Eltern zu null gesetzt und ich habe Fehler einen Runtime free () in Form Konstruktor und Methoden Afterconstruction aber in beiden Fällen zu nennen.


Als spezifischere, bekam ich eine Zugriffsverletzung (EAccessViolation). Es scheint, François recht, wenn er sagt, dass Komponenten im Rahmen costruction Verwirrungen mit Formular steuert Housekeeping zu befreien.

War es hilfreich?

Lösung

Diese generische Routine arbeitet entweder mit einem Formular oder Frame (aktualisiert, um eine Unterklasse für die neue Steuerung zu verwenden):

function ReplaceControlEx(AControl: TControl; const AControlClass: TControlClass; const ANewName: string; const IsFreed : Boolean = True): TControl;
begin
  if AControl = nil then
  begin
    Result := nil;
    Exit;
  end;
  Result := AControlClass.Create(AControl.Owner);
  CloneProperties(AControl, Result);// copy all properties to new control
  // Result.Left := AControl.Left;   // or copy some properties manually...
  // Result.Top := AControl.Top;
  Result.Name := ANewName;
  Result.Parent := AControl.Parent; // needed for the InsertControl & RemoveControl magic
  if IsFreed then
    FreeAndNil(AControl);
end;

function ReplaceControl(AControl: TControl; const ANewName: string; const IsFreed : Boolean = True): TControl;
begin
  if AControl = nil then
    Result := nil
  else
    Result := ReplaceControlEx(AControl, TControlClass(AControl.ClassType), ANewName, IsFreed);
end;

diese Routine mit den Eigenschaften der neuen Steuerung zu übergeben

procedure CloneProperties(const Source: TControl; const Dest: TControl);
var
  ms: TMemoryStream;
  OldName: string;
begin
  OldName := Source.Name;
  Source.Name := ''; // needed to avoid Name collision
  try
    ms := TMemoryStream.Create;
    try
      ms.WriteComponent(Source);
      ms.Position := 0;
      ms.ReadComponent(Dest);
    finally
      ms.Free;
    end;
  finally
    Source.Name := OldName;
  end;
end;

verwenden Sie es wie:

procedure TFrame1.AfterConstruction;
var
  I: Integer;
  NewEdit: TMyEdit;
begin
  inherited;
  NewEdit := ReplaceControlEx(Edit1, TMyEdit, 'Edit2') as TMyEdit;
  if Assigned(NewEdit) then
  begin
    NewEdit.Text := 'My Brand New Edit';
    NewEdit.Author := 'Myself';
  end;
  for I:=0 to ControlCount-1 do
  begin
    ShowMessage(Controls[I].Name);
  end;
end;

ACHTUNG: . Wenn Sie dies innerhalb des Afterconstruction des Rahmens tun, passen sie, dass die Hosting-Formular Bau noch nicht abgeschlossen ist
Befreit dort Controls, könnte eine Menge Probleme verursachen, wie Sie mit Formular-Steuerelemente Housekeeping sind vermasselt.
Sehen Sie, was Sie bekommen, wenn Sie versuchen, die neue Beschriftung bearbeiten lesen in der Showmessage anzuzeigen ...
In diesem Fall würde die Sie verwenden möchten
  ... ReplaceControl (Edit1, 'EDIT2', false )
und dann eine
  ... FreeAndNil (Edit1)
später.

Andere Tipps

Sie haben RemoveControl der TEdit der Eltern rufen Sie die Kontrolle zu entfernen. Verwenden Sie Insert das neue Steuerelement hinzuzufügen.

var Edit2: TEdit;
begin
  Edit2 := TEdit.Create(self);
  Edit2.Left := Edit1.Left;
  Edit2.Top := Edit2.Top;
  Edit1.Parent.Insertcontrol(Edit2);
  TWinControl(Edit1.parent).RemoveControl(Edit1);
  Edit1.Free;
end;

Ersetzen TEdit.Create auf die Klasse, die Sie verwenden möchten, und kopieren Sie alle Eigenschaften, die Sie brauchen, wie ich mit Links und Oben hat.

Sie können tatsächlich nutzen RTTI (Blick in die Typinfo-Einheit), um alle passende Objekte zu klonen. Ich schrieb Code für diese eine Weile zurück, aber ich kann es jetzt nicht finden. Ich werde Augen offen halten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top