문제

예를 들어 런타임에 (조건부) 인스턴스화 된 하위 클래스 구성 요소로 테디를 교체하고 자유롭게 할 수 있습니까? 그렇다면 언제 어떻게해야합니까? 부모를 NIL로 설정하고 양식 생성자 및 애프터 건설 방법으로 free ()를 호출하려고했지만 두 경우 모두 런타임 오류가 발생했습니다.


보다 구체적으로, 나는 액세스 위반 오류 (eaccessviolation)를 받았습니다. François는 프레임 화재로 구성 요소를 자유롭게하는 것이 형태 제어 하우스 키핑을 엉망으로 말할 때 옳은 것 같습니다.

도움이 되었습니까?

해결책

이보다 일반적인 루틴은 양식 또는 프레임으로 작동합니다 (새 컨트롤을 위해 서브 클래스를 사용하도록 업데이트 됨).

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;

이 루틴을 사용하여 속성을 새로운 컨트롤에 전달합니다.

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;

다음과 같이 사용하십시오.

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;

주의: 프레임의 애프터 건설 내부 에서이 작업을 수행하는 경우 호스팅 양식 구조가 아직 완료되지 않았 음을주의하십시오.
거기에 컨트롤을 자유롭게하면 양식 컨트롤 하우스 키핑을 엉망으로 만들면서 많은 문제가 발생할 수 있습니다.
ShowMessage에 표시 할 새 편집 캡션을 읽으려고 할 때 얻는 것이 무엇인지 확인하십시오 ...
이 경우 사용하고 싶을 것입니다
... replacecontrol (edit1, 'edit2', 거짓)
그리고 a
... FreeAndnil (edit1)
나중에.

다른 팁

컨트롤을 제거하려면 Tedit의 부모의 removecontrol을 호출해야합니다. InsertControl을 사용하여 새 컨트롤을 추가하십시오.

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;

Tedit.을 교체하고 싶은 클래스로 만듭니다. 그리고 내가 왼쪽과 상단과 같이 필요한 모든 속성을 복사하십시오.

실제로 RTTI (TypInfo 장치를 보면)를 사용하여 모든 일치하는 속성을 복제 할 수 있습니다. 나는 이것을 위해 코드를 썼지 만 지금은 찾을 수 없습니다. 나는 계속보고있을 것이다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top