VCL рдШрдЯрдХ рдХреНрд▓реЛрдирд┐рдВрдЧ

FMX рдореЗрдВ Embarcadero рд╕рд╛рд╡рдзрд╛рдиреАрдкреВрд░реНрд╡рдХ рдХреНрд▓реЛрдирд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдХрднреА-рдХрднреА рдбреЗрд╡рд▓рдкрд░ рдХреЗ рдЬреАрд╡рди рдХреЛ рд╕реБрдЦрдж рдмрдирд╛ рд╕рдХрддрд╛ рд╣реИред VCL рд░рди-рдЯрд╛рдЗрдо рдореЗрдВ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдХреНрд▓реЛрдирд┐рдВрдЧ рдЯреВрд▓ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред


рдЗрд╕рдХрд╛ рдХреНрдпрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рдмреЗрд╢рдХ, рдПрдХ рдкреИрдЯрд░реНрди рдореЗрдВ рджреГрд╢реНрдп рдШрдЯрдХреЛрдВ рдХреЛ рдХреНрд▓реЛрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдлрд╛рдпрджреЗ рдФрд░ рдиреБрдХрд╕рд╛рди, рдореИрдВ рдЧреБрд░реБ рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝рдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВред

рдЕрдЧрд▓рд╛, рдореИрдВ рд╕рд┐рд░реНрдл рдХреЛрдб рдФрд░ рдЕрдкрдиреА рдЯрд┐рдкреНрдкрдгреА рджреВрдВрдЧрд╛:

unit Clonable; interface uses System.SysUtils, System.Classes, System.TypInfo, Vcl.Controls, StrUtils; { extending } type TClonable = class(TComponent) private procedure CopyComponentProp(Source, Target: TObject; aExcept: array of string); public function Clone(const AOwner: TComponent; aExcept: array of string): TComponent; end; implementation procedure TClonable.CopyComponentProp(Source, Target: TObject; aExcept: array of string); var I, Index: Integer; PropName: string; Source_PropList , Target_PropList : PPropList; Source_NumProps , Target_NumProps : Word; Source_PropObject, Target_PropObject: TObject; { property list finder } function FindProperty(const PropName: string; PropList: PPropList; NumProps: Word): Integer; var I: Integer; begin Result:= -1; for I:= 0 to NumProps - 1 do if CompareStr(PropList^[I]^.Name, PropName) = 0 then begin Result:= I; Break; end; end; begin if not Assigned(Source) or not Assigned(Target) then Exit; Source_NumProps:= GetTypeData(Source.ClassInfo)^.PropCount; Target_NumProps:= GetTypeData(Target.ClassInfo)^.PropCount; GetMem(Source_PropList, Source_NumProps * SizeOf(Pointer)); GetMem(Target_PropList, Target_NumProps * SizeOf(Pointer)); try { property list } GetPropInfos(Source.ClassInfo, Source_PropList); GetPropInfos(Target.ClassInfo, Target_PropList); for I:= 0 to Source_NumProps - 1 do begin PropName:= Source_PropList^[I]^.Name; if (AnsiIndexText('None' , aExcept ) = -1) and ((AnsiIndexText(PropName, ['Name', 'Left', 'Top']) <> -1) or (AnsiIndexText(PropName, aExcept ) <> -1)) then Continue; Index:= FindProperty(PropName, Target_PropList, Target_NumProps); if Index = -1 then Continue; {no property found} { compare types } if Source_PropList^[I]^.PropType^.Kind <> Target_PropList^[Index]^.PropType^.Kind then Continue; case Source_PropList^[I]^.PropType^^.Kind of tkClass: begin Source_PropObject:= GetObjectProp(Source, Source_PropList^[I ]); Target_PropObject:= GetObjectProp(Target, Target_PropList^[Index]); CopyComponentProp(Source_PropObject, Target_PropObject, ['None']); end; tkMethod: SetMethodProp(Target, PropName, GetMethodProp(Source, PropName)); else SetPropValue(Target, PropName, GetPropValue(Source, PropName)); end; end; finally FreeMem(Source_PropList); FreeMem(Target_PropList); end; end; function IsUniqueGlobalNameProc(const Name: string): Boolean; begin if Length(Name) = 0 then Result := True else Result := Not Assigned(FindGlobalComponent(Name)); end; function TClonable.Clone(const AOwner: TComponent; aExcept: array of string): TComponent; var S: TStream; SaveName: string; Reader: TReader; FSaveIsUniqueGlobalComponentName: TIsUniqueGlobalComponentName; I: Integer; Child: TComponent; LComponent: TComponent; begin { for simple compatible } LComponent:=Self; { register self type } RegisterClass(TPersistentClass(LComponent.ClassType)); S := TMemoryStream.Create; Result := nil; try { store } SaveName := LComponent.Name; Self.Name := ''; S.WriteComponent(LComponent); LComponent.Name := SaveName; S.Position := 0; { load } FSaveIsUniqueGlobalComponentName := IsUniqueGlobalComponentNameProc; IsUniqueGlobalComponentNameProc := IsUniqueGlobalNameProc; try Reader := TReader.Create(S, 4096); try Result := TComponent(Reader.ReadRootComponent(nil)); if Assigned(AOwner) then AOwner.InsertComponent(Result); finally Reader.Free; if not Assigned(Result) then Result := TComponentClass(LComponent.ClassType).Create(AOwner); end; finally IsUniqueGlobalComponentNameProc := FSaveIsUniqueGlobalComponentName; end; finally S.Free; end; {parent} if (LComponent is TControl) and (LComponent as TControl).HasParent then (Result as TControl).Parent:=(LComponent as TControl).Parent; { copy propertys value } CopyComponentProp(LComponent, Result, aExcept); { childs } if (LComponent is TWinControl) and ((LComponent as TWinControl).ControlCount > 0) then for I := 0 to (LComponent as TWinControl).ControlCount - 1 do begin Child:= TClonable( (LComponent as TWinControl). Controls[I]). Clone(LComponent, aExcept); if (Child is TControl) then (Child as TControl).Parent:=(Result as TWinControl); end; end; end. 


рдЙрдкрдпреЛрдЧ рдЙрджрд╛рд╣рд░рдг:
 procedure TForm1.Button1Click(Sender: TObject); var Clone: TPanel; begin Clone:=TPanel(TClonable(Panel1).Clone(Self, [])); Clone.Top:=Panel1.Top+Panel1.Height; end; 


TClonable рд╡рд░реНрдЧ рдХреЗ рдХреНрд▓реЛрди рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд┐рд╡рд░рдг:
рдлрд╝рдВрдХреНрд╢рди рдХреНрд▓реЛрди (const AOwner: TComponent; aExcept: string of string): TComponent;


рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдШрдЯрдХреЛрдВ рдХреЛ рдХреЙрдкреА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ: рдмрдЪреНрдЪреЗ рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреА рдирдХрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рддрдВрддреНрд░ рдХреЗ рд╕рд╛рде рдЬреЛ рдЯреНрд╡рд┐рдирдХрдВрдЯреНрд░реЛрд▓ рд╡рдВрд╢рдЬ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ; рдШрдЯрдирд╛рдУрдВ рдХрд╛ рдкреБрдирд░реНрдореВрд▓реНрдпрд╛рдВрдХрди; рдЕрдирд╛рд╡рд╢реНрдпрдХ рдЧреБрдгреЛрдВ рдХреЛ рдЦрддреНрдо рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ред

рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ рдореИрдВ рдПрдХ рдирд╡рд╛рдЪрд╛рд░ рд╣реЛрдиреЗ рдХрд╛ рдирд╛рдЯрдХ рдирд╣реАрдВ рдХрд░рддрд╛, рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдПрдХ рд╕рд╛рдЗрдХрд┐рд▓ рд╣реИ, рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдмреИрд╕рд╛рдЦреА рдирд╣реАрдВ рд╣реИ))

Source: https://habr.com/ru/post/In204678/


All Articles