Fórum Copiar propriedades, métodos e eventos dum objeto para outro #291816
16/08/2005
0
se eu tenho um botão com algumas propriedades configuradas e um evento de clique, eu crio um outro botão em tempo de execução e quero que esse novo botão faça exatamente o mesmo que o primeiro, uma cópia.
Eu conheço o método Assign, mas não consigo usar pq simplesmente ele não funciona, tipo
Button2.Assign(Button1);
Dá erro dizendo que Não é possivel atribuir um TButton a um TButton!
Alguem pode me explicar?
[color=green:0c7d85de66]Título editado por gandalf.nho. Procure usar títulos mais explicativos (´Dúvida avançada...´)[/color:0c7d85de66]
Carlos Filho
Curtir tópico
+ 0Posts
16/08/2005
Massuda
No seu caso, você pode copiar uma a uma as propriedades de um botão para outro. Tem outra alternativa mais sofisticada, baseada em streams.
Gostei + 0
16/08/2005
Adriano Santos
Coloque um título mais explicativo nos seus posts, fica mais fácil pra todos, ok?
Gostei + 0
16/08/2005
Carlos Filho
Coloque um título mais explicativo nos seus posts, fica mais fácil pra todos, ok?[/quote:82b30fa074]
Eu até pensei em por, mas (acho que estou errado) uma vez fiz isso e levei a mesma bronca dizendo que não se deve por perguntas no titulo.
Mas acho que deve ter sido em outro forum...
Gostei + 0
16/08/2005
Carlos Filho
É exatamente isso que eu to fazendo agora, mas como eu pretendo criar uma função genérica, seria mais interessante criar um objeto temporário e copiar as propriedades e eventos de uma só vez...
Como seria usando Streams? Funciona mesmo ou tem limitações? (que só seriam resolvidas se o Assign funcionasse bem)
Gostei + 0
16/08/2005
Adriano Santos
Coloque um título mais explicativo nos seus posts, fica mais fácil pra todos, ok?[/quote:8f062edce9]
Eu até pensei em por, mas (acho que estou errado) uma vez fiz isso e levei a mesma bronca dizendo que não se deve por perguntas no titulo.
Mas acho que deve ter sido em outro forum...[/quote:8f062edce9]
Tranquilo véio, não é bronca não. É que tem usuário que não entra mesmo no tópico se o título não estiver muito explicado...eu mesmo sou um deles, entrei por curisoso neste...rsss...se preferir dá uma olhada nas regras de conduta deste fórum, aki é todo mundo camarada pode comprovar.
[url=http://forum.clubedelphi.net/viewtopic.php?t=6689]Regras de conduta[/url]
Gostei + 0
16/08/2005
Massuda
Gostei + 0
16/08/2005
Carlos Filho
Minha idéia era simplesmente aplicar propriedades em um TEdit por exemplo a fim de tornar seu texto centralizado.
O que eu tava fazendo era type casts de um TEdit para um TAlignEdit (q eu criei) e aplicava as propriedadas recriando o componente, mas para isso eu tinha de antes copiar as propriedades que seriam perdidas com o Free.
Minha dúvida principal nesse tópico seria portanto PORQUE O ASSING NUNCA FUNCIONA QUANDO A GENTE PRECISA DELE??
Sobre as regras do forum eu tenho de admintir que nunca li! :oops: Mas não sou novato! heehhe é desleixo mesmo! :wink:
Gostei + 0
12/12/2005
Rodc
Gostei + 0
13/12/2005
Rodc
É verdade o metodo Assign do TPersistent apenas chama o método AssignError, que mostra o erro descrito. Não tem código nenhum lá fazendo a duplicação do componente. Que estranho!!! :shock:
Gostei + 0
04/01/2006
Rodc
Depois de muito pesquisar no google, depois de muito tentar entender Inglês e depois de muitos testes, consegui resolver o problema da cópia de componentes. Para que outros também não tenham que se matar de pesquisar... vou disponibilizar o código.
O código foi pego do site de um dos programadores da Borland (http://www.blong.com) mas uma unit do BCB tá com erro. Depois de muito pesquisar encontrei a solução e corrigi o código do cara.
Unit RTTIUnit.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
pragma hdrstop
include "RTTIUnit.h"
include <TypInfo.hpp>
include <Registry.hpp>
include <alloc.h>
const NoDefault = 0x80000000;
//V3 TTypeKind ends in tkInterface
//V4 TTypeKind ends in tkDynArray
#if __BCPLUSPLUS__ < 0x540
define tkPropsWithDefault (System::Set<Typinfo::TTypeKind, tkUnknown, tkInterface> () \
<< tkInteger << tkChar << tkEnumeration << tkSet )
else
define tkPropsWithDefault (System::Set<Typinfo::TTypeKind, tkUnknown, tkDynArray> () \
<< tkInteger << tkChar << tkEnumeration << tkSet )
endif
void SetDefaults(TObject *Obj)
{
//Find out how many properties we´ll be considering
int Count = GetPropList((PTypeInfo)(Obj->ClassInfo()), tkPropsWithDefault, NULL);
//Allocate memory to hold their RTTI data
PPropList List = (PPropList) new PPropInfo[Count];
try
{
//Get hold of the property list in our new buffer
GetPropList((PTypeInfo)(Obj->ClassInfo()), tkPropsWithDefault, List);
//Loop through all the selected properties
for (int i = 0; i < Count; i++)
#if __BCPLUSPLUS__ > 0x540
//If there is supposed to be a default value...
if ((*List[i])->Default != NoDefault)
//...then jolly well set it
SetOrdProp(Obj, *List[i], (*List[i])->Default);
else
//If there is supposed to be a default value...
if (List[i]->Default != NoDefault)
//...then jolly well set it
SetOrdProp(Obj, List[i], List[i]->Default);
endif
}
__finally
{
delete[] List;
}
}
void CopyObject(TObject *ObjFrom, TObject *ObjTo)
{
//Iterate thru all published fields and
//properties of source copying them to target
//Find out how many properties we´ll be considering
int Count = GetPropList((PTypeInfo)(ObjFrom->ClassInfo()), tkAny, NULL);
//Allocate memory to hold their RTTI data
PPropList PropInfos = (PPropList) new PPropInfo[Count];
try
{
//Get hold of the property list in our new buffer
GetPropList((PTypeInfo)(ObjFrom->ClassInfo()), tkAny, PropInfos);
//Loop through all the selected properties
for (int i = 0; i < Count; i++)
{
PPropInfo PropInfo = GetPropInfo((PTypeInfo)ObjTo->ClassInfo(), (*PropInfos)[i]->Name);
//Check the general type of the property
//and read/write it in an appropriate way
switch ((*(*PropInfos)[i]->PropType)->Kind)
{
case tkClass:
{
//Ignore properties which are themselves objects
break;
}
case tkInteger:;
case tkChar:;
case tkEnumeration:;
case tkSet:;
case tkWChar:
{
int OrdVal = GetOrdProp(ObjFrom, (*PropInfos)[i]);
if (PropInfo)
SetOrdProp(ObjTo, PropInfo, OrdVal);
break;
}
case tkFloat:
{
double FloatVal = GetFloatProp(ObjFrom, (*PropInfos)[i]);
if (PropInfo)
SetFloatProp(ObjTo, PropInfo, FloatVal);
break;
}
case tkWString:;
case tkLString:;
case tkString:
{
//Avoid copying "Name" - components must have unique names
if (UpperCase((*PropInfos)[i]->Name) != "NAME")
{
String StrVal = GetStrProp(ObjFrom, (*PropInfos)[i]);
if (PropInfo)
SetStrProp(ObjTo, PropInfo, StrVal);
}
break;
}
case tkMethod:
{
TMethod MethodVal = GetMethodProp(ObjFrom, (*PropInfos)[i]);
if (PropInfo)
SetMethodProp(ObjTo, PropInfo, MethodVal);
}
}
}
}
__finally
{
delete[] PropInfos;
}
}
TRegIniFile *Reg;
const String Section = "Property Values";
//---------------------------------------------------------------------------
void ReadProp(TObject *Obj, const String PropName)
{
PPropInfo Prop =
GetPropInfo((PTypeInfo)Obj->ClassInfo(), PropName);
if (!Prop)
throw Exception("Property ¬s not found in ¬s class",
ARRAYOFCONST((PropName, Obj->ClassName())));
//For each case, read a value from the registry, using
//the current value as the default, then use that read
//value to set the property
switch ((*Prop->PropType)->Kind)
{
case tkWString:;
case tkLString:;
case tkString:
SetStrProp(Obj, Prop,
Reg->ReadString(Section, PropName, GetStrProp(Obj, Prop)));
break;
case tkInteger:;
case tkChar:;
case tkSet:;
case tkWChar:;
SetOrdProp(Obj, Prop,
Reg->ReadInteger(Section, PropName, GetOrdProp(Obj, Prop)));
break;
case tkFloat:
SetFloatProp(Obj, Prop, StrToFloat(
Reg->ReadString(Section, PropName,
FloatToStr(GetFloatProp(Obj, Prop)))));
break;
//Enums are written out as strings
case tkEnumeration:
SetOrdProp(Obj, Prop, GetEnumValue(
*Prop->PropType, Reg->ReadString(Section, PropName,
GetEnumName(*Prop->PropType, GetOrdProp(Obj, Prop)))));
}
}
void ReadProps(TObject *Obj, const String *PropNames, const int PropNames_Size)
{
for (int i = 0; i <= PropNames_Size; i++)
ReadProp(Obj, PropNames[i]);
}
void WriteProp(TObject *Obj, const String PropName)
{
PPropInfo Prop =
GetPropInfo((PTypeInfo)Obj->ClassInfo(), PropName);
if (!Prop)
throw Exception("Property ¬s not found in ¬s class",
ARRAYOFCONST((PropName, Obj->ClassName())));
//For each case, write the property value to the registry
switch ((*Prop->PropType)->Kind)
{
case tkWString:;
case tkLString:;
case tkString:
Reg->WriteString(Section, PropName, GetStrProp(Obj, Prop));
break;
case tkInteger:;
case tkChar:;
case tkSet:;
case tkWChar:;
Reg->WriteInteger(Section, PropName, GetOrdProp(Obj, Prop));
break;
case tkFloat:
Reg->WriteString(Section, PropName, FloatToStr(GetFloatProp(Obj, Prop)));
break;
//Enums are written out as strings
case tkEnumeration:
Reg->WriteString(Section, PropName,
GetEnumName(*Prop->PropType, GetOrdProp(Obj, Prop)));
}
}
void WriteProps(TObject *Obj, const String *PropNames, const int PropNames_Size)
{
for (int i = 0; i <= PropNames_Size; i++)
WriteProp(Obj, PropNames[i]);
}
void Initialization(void)
{
Reg = new TRegIniFile("Software\\BLong\\Property Saver");
}
pragma startup Initialization
void Finalization(void)
{
delete Reg;
}
pragma exit Finalization
pragma package(smart_init)Cabeçalho da unit RTTIUnit.h
//--------------------------------------------------------------------------- #ifndef RTTIUnitH define RTTIUnitH include <vcl.h> pragma hdrstop //--------------------------------------------------------------------------- void SetDefaults(TObject *Obj); void CopyObject(TObject *ObjFrom, TObject *ObjTo); void ReadProp(TObject *Obj, const String PropName); void ReadProps(TObject *Obj, const String *PropNames, const int PropNames_Size); void WriteProp(TObject *Obj, const String PropName); void WriteProps(TObject *Obj, const String *PropNames, const int PropNames_Size); //--------------------------------------------------------------------------- endif
a unit TypInfo.hpp ($(BCB)\Source\vcl) tem que ser modificada pois está em conflito com a System.hpp.
Troque
typedef PPropInfo *PPropList;
por
typedef TPropList *PPropList;
e troque
#define tkAny (System::Set<TTypeKind, tkUnknown, tkDynArray> () << TTypeKind(0) << TTypeKind(1) << TTypeKind(2) << TTypeKind(3) << TTypeKind(4) << TTypeKind(5) << TTypeKind(6) << TTypeKind(7) << TTypeKind(8) << TTypeKind(9) << TTypeKind(10) << TTypeKind(11) << TTypeKind(12) << TTypeKind(13) << TTypeKind(14) << TTypeKind(15) << TTypeKind(16) << TTypeKind(17) ) define tkMethods (System::Set<TTypeKind, tkUnknown, tkDynArray> () << TTypeKind(8) ) define tkProperties (System::Set<TTypeKind, tkUnknown, tkDynArray> () << TTypeKind(1) << TTypeKind(2) << TTypeKind(3) << TTypeKind(4) << TTypeKind(5) << TTypeKind(6) << TTypeKind(7) << TTypeKind(9) << TTypeKind(10) << TTypeKind(11) << TTypeKind(12) << TTypeKind(13) << TTypeKind(14) << TTypeKind(15) << TTypeKind(16) << TTypeKind(17) )
por
#define tkAny (System::Set<Typinfo::TTypeKind, tkUnknown, tkDynArray> () << Typinfo::TTypeKind(0) << Typinfo::TTypeKind(1) << Typinfo::TTypeKind(2) << Typinfo::TTypeKind(3) << Typinfo::TTypeKind(4) << Typinfo::TTypeKind(5) << Typinfo::TTypeKind(6) << Typinfo::TTypeKind(7) << Typinfo::TTypeKind(8) << Typinfo::TTypeKind(9) << Typinfo::TTypeKind(10) << Typinfo::TTypeKind(11) << Typinfo::TTypeKind(12) << Typinfo::TTypeKind(13) << Typinfo::TTypeKind(14) << Typinfo::TTypeKind(15) << Typinfo::TTypeKind(16) << Typinfo::TTypeKind(17) ) define tkMethods (System::Set<Typinfo::TTypeKind, tkUnknown, tkDynArray> () << Typinfo::TTypeKind(8) ) define tkProperties (System::Set<Typinfo::TTypeKind, tkUnknown, tkDynArray> () << Typinfo::TTypeKind(1) << Typinfo::TTypeKind(2) << Typinfo::TTypeKind(3) << Typinfo::TTypeKind(4) << Typinfo::TTypeKind(5) << Typinfo::TTypeKind(6) << Typinfo::TTypeKind(7) << Typinfo::TTypeKind(9) << Typinfo::TTypeKind(10) << Typinfo::TTypeKind(11) << Typinfo::TTypeKind(12) << Typinfo::TTypeKind(13) << Typinfo::TTypeKind(14) << Typinfo::TTypeKind(15) << Typinfo::TTypeKind(16) << Typinfo::TTypeKind(17) )
No meu caso vou implementar ainda para a função copiar todos os componentes childrens do componente passado por referencia. Ex. Copiar todos os edits e Labels que estiverem dentro de um TPanel.
Gostei + 0
05/01/2006
Rodc
Gostei + 0
08/12/2006
Tpoeta
Gostei + 0
16/01/2008
Micheus
Como este tópico foi referenciado em outro forum (DevMedia), e não havia sido apresentada uma solução aqui, segue o [url=http://www.activedelphi.com.br/forum/viewtopic.php?p=208641&highlight=#208641]link[/url] com uma proposta de procedure para clonagem de componentes em run-time.
Abraços
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)