Fórum Como obter a variável de instância de uma classe? #370407
12/05/2009
0
Considerando que eu tenho estas classes com as variáveis de instância ncliente e nfornecedor
//classe cliente
type
Tncliente = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
ncliente: Tncliente;
Initialization
Classes.RegisterClass(Tncliente)
Finalization
Classes.UnRegisterClass(Tncliente) //classe fornecedor
type
Tnfornecedor = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
nfornecedor: Tnfornecedor;
Initialization
Classes.RegisterClass(Tnfornecedor)
Finalization
Classes.UnRegisterClass(Tnfornecedor) e dado o código abaixo:
procedure TnPrincipal.CriarForm(TjanelaDestino : string); var AClassJanelaDestino : TFormClass; AFormJanelaDestino : TForm; begin AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino)); //TjanelaDestino recebe Tncliente ou Tnfornecedor if AClassJanelaDestino <> nil then begin Application.CreateForm(AClassJanelaDestino, AFormJanelaDestino); end else raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´); end;
Em vez de jogar o Pointer em AFormJanelaDestino,
como poderia jogar o pointer diretamente na variável de instância da classe passada como parâmetro?
procedure TnPrincipal.CriarForm(TjanelaDestino : string); var AClassJanelaDestino : TFormClass; /////////AFormJanelaDestino : TForm; begin AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino)); //TjanelaDestino recebe Tncliente ou Tnfornecedor if AClassJanelaDestino <> nil then begin Application.CreateForm(AClassJanelaDestino, aqui variável de isntância da classe Tncliente ou TnFornecedor); end else raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´); end;
Ou seja, temos como pegar a classe passando uma string. A pergunta que fica é se tem como pegar a variável de instância de forma semelhante como pegamos a classe?
Agradeço a todos que puderem contribuir
Delmar
Delmar
Curtir tópico
+ 0Posts
13/05/2009
.lg.
Se não for o form principal, descarte a ideia de:
var ncliente: Tncliente
Você pode criar sua classe sem isso. Infelizmente, eu sei o porque o form principal do delphi o cria, mas não sei explicar o porque.
Se for units diferentes, lembrese de dar um [b:d1754e7728]Uses[/b:d1754e7728] na unit que vc quer usar.
Use o nome de sua classe como o tipo de sua variável.
AFormJanelaDestino: Tnfornecedor;
Instancia:
AFormJanelaDestino := TnFornecedor.Create;
E quando não precisar dela, destrua e limpe da memoria.
FreeAndNil(AFormJanelaDestino);
Se eu estiver errado favor me corrigir.
Eu faço assim.
Espero que lhe ajude.
Gostei + 0
13/05/2009
Delmar
Como esse procedimento é uma especie de factory de TForms, baseado no exemplo, ele pode receber um Tncliente ou um Tnfornecedor, então eu não posso ter um tipo fixo. Ao menos que existe como fazer a declaração do tipo se auto-ajustar ao parâmetro passado.
Por outro lado, eu penso que se o Application.CreateForm saber criar um formulário e ao mesmo tempo setar sua variável de instância para apontar para o objeto criado, deve existir um jeito de fazer isso, pois por traz dos bastidores ele faz isso de alguma forma, acredito.
Gostei + 0
13/05/2009
.lg.
Minhas desculpas,
Abraços.
Att,
.lg.
Gostei + 0
13/05/2009
Delmar
E os colegas que trabalham mais intensamente com POO ou que têm mais contato com as certificações do Delphi ariscariam um palpite de como resolver esta situação?
Gostei + 0
14/05/2009
Marco Salles
procedure TForm1.CriarForm(TjanelaDestino : string); begin try with TComponentClass(findclass(TjanelaDestino)).Create(nil) as TForm do begin showModal; free; end; except Raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´); end; end;
bem , mas eu gosto e uso é o factory methods
pode ser visto em :
http://forum.devmedia.com.br/viewtopic.php?t=74823&highlight=factory
em seguida aprece um nova idéia usando Interfaces . Mas esta eu não
coloquei emlinha de produç]ao
http://forum.devmedia.com.br/viewtopic.php?p=328239&highlight=#328239
Gostei + 0
14/05/2009
Delmar
o que eu quero é isto:
Application.CreateForm(AClassJanelaDestino, aqui variável de isntância da classe Tncliente ou TnFornecedor);
Ou seja, quando Application.CreateForm criar uma instância da classe, fazer com que a variável de instância daquela classe aponte para o objeto criado.
Em outras palavras:
Se foi passado TnCliente, quando Application.CreateForm criar o objeto, a variável nCliente deve apontar para o endereço do objeto criado.
Se foi passado TnFornecedor, quando Application.CreateForm criar o objeto, a variável nFornecedor deve apontar para o endereço do objeto criado.
Do meu entendimento, quando fizemos um Application.CreateForm o CreateForm faz o trabalho de criar um objeto e faz com que a variável aponte para este objeto.
O problema é que, no exemplo que estou propondo, temos uma factory e não estou conseguindo pegar a variável da classe passada como parâmetro, pois eu posso encontrar diferentes classes de acordo com uma string passada como parâmetro para o comando TFormClass(GetClass(TjanelaDestino))
Ou seja, dada uma string, eu consigo obter a classe usando GetClass, mas ainda não descobri como pegar a sua variável. Teria que ter um comando GetVariable para fazer o que faz GetClass, só que GetClass pega a Classe e GetVariable deveria pegar a variável.
Pronto, expliquei de várias maneiras a mesma coisa.
Gostei + 0
14/05/2009
Marco Salles
Mas se o proprio Application.CreateForm qnd cria o Objeto ele devolve o
ponteiro para o Objeto Recem Criado
não entendo qnd vc disse que o delphi faz isto atras dos bastidores
se tudo indica que ele usa a classe e a variavel digamos assim???
p:s Não estou usando uma linguagem tecnica
Gostei + 0
14/05/2009
Delmar
Visitei o método CriarForm do Tapplication e evolui um pouco
Consegui algum progresso assim
procedure TnPrincipal.CriarForm(TjanelaDestino : string; var Reference); var AClassJanelaDestino : TFormClass; begin AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino)); //TjanelaDestino recebe Tncliente ou Tnfornecedor if AClassJanelaDestino <> nil then begin Application.CreateForm(AClassJanelaDestino, TForm(Reference)); TForm(Reference).Show; end else raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´); end;
Só que dessa forma minha chamada fica assim
CriarForm(´TnCliente´, nCliente);
E eu queria assim:
CriarForm(´TnCliente´);
Gostei + 0
14/05/2009
Delmar
Sim, mas a classe eu estou pegando com GetClass, dada uma string contendo o nome da classe, mas eu não posso colocar ali na variável fixo nCliente ou nFornecedor, porque eu não sei qual destes dois termos, vai depender de qual classe eu passei. Só que mesmo tendo pego a classe eu não sei extrair de dentro dela o nome da variável.
Sua linguagem está ótima, quanto mais técnica, melhor. Eu não entendo muito de POO, mas programo estruturado em Delphi desde 98, então pode mandar bala, se eu não entender algo, eu vou pro Help do Delphi.
o meu problema não é usar estes comandos
Isso aí eu tiro de letra, o desafio é pegar a variável, qdo fornecido apenas uma string representando o nome da classe.
Gostei + 0
14/05/2009
Marco Salles
Sera que vc por acaso não estaria se refrindo ao FindClass() ????
var AClassJanelaDestino : TFormClass; variavel:Tform; begin AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino)); //TjanelaDestino recebe Tncliente ou Tnfornecedor if AClassJanelaDestino <> nil then begin variavel:=Tform(findclass(TJanelaDestino)); Application.CreateForm(AClassJanelaDestino,variavel); variavel.Show; end else raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´); end;
Gostei + 0
14/05/2009
Fabriciocolombo
Factories, normalmente são functions e não procedures, então vc poderia fazer assim:
function TFactoryForm.CriarForm(TjanelaDestino : string): TForm; var AClassJanelaDestino : TFormClass; begin AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino)); //TjanelaDestino recebe Tncliente ou Tnfornecedor if AClassJanelaDestino <> nil then begin Result := AClassJanelaDestino.Create(nil); end else raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´); end;
e chamar assim:
procedure x; var vClient: TForm; begin vClient := FactoryForm.CriarForm(´Tncliente´); try vClient.ShowModal; finally FreeAndNil(vClient); end; end;
Gostei + 0
14/05/2009
Delmar
Não. FindClass está funcionando perfeitamente.
Gostei + 0
14/05/2009
Delmar
Digamos que seja software legado ou também para fins didático.
Como ainda não consegui o que eu queria eu mudei para isso:
procedure TnPrincipal.CMavisos(var Msg: TMessage); var AClassJanelaDestino: TFormClass; AForm: TForm; CriarForm: procedure(aCodigo: string) of object; begin AClassJanelaDestino := TFormClass(GetClass(TjanelaDestino)); TPersistent if AClassJanelaDestino <> nil then begin AForm := AClassJanelaDestino.Create(self); try @CriarForm := AForm.MethodAddress(´CriarForm´); if @CriarForm <> nil then CriarForm(IntToStr(Msg.WParam)) else raise Exception.Create(´O procedimento CriarForm não está disponível na Classe ´ + TjanelaDestino); AForm.Free; except AForm.Free; raise; end; end else raise Exception.Create(´A Classe´ + TjanelaDestino + ´ não existe´); end;
Como MethodAddress é um método de classe eu criei dentro de TnCliente e também dentro de TnFornecedor o método CriarForm. Agora sim, em cada classe, dentro do CriarForm, posso executar, respectivamente, o seguinte:
Application.CreateForm(TnCliente, nCliente);
e
Application.CreateForm(TnFornecedor, nFornecedor);
e com isso deixar o legado nCliente e nFornecedor abastecido com o endereço do objeto.
Sim, eu conheço essa construção usando função que retorna TForm.
Porém, eu venho de um PostMessage, ou seja, a janela que disparou PostMessage pode até já ter sido destruída. Então eu não posso retornar nada para a janela que dispara PostMessage. E tem mais, a janela que dispara PostMessage não sabe nada sobre TnCliente e nem sobre TnFornecedor, caso contrário, eu poderia passar a classe a a referencia, e aí teria sido uma maravilha, era só fazer a função tal qual vc me sugeriu.
Gostei + 0
11/06/2018
Smart Sistemas
Estou tentando fazer exatamente a mesma coisa que você. Conseguiu uma solução para isso?
Gostei + 0
11/06/2018
Emerson Nascimento
CriarForm(´TnCliente´);
ou
CriarForm(´Tnfornecedor´);
?
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)