Inibir duplicidade do Form na procedure
Pessoal,
Tenho uma aplicação onde uso Forms do tipo fsMDIChild
Entao para dar uma agilizada no trabalho gostaria de criar uma Procedure para criar os Forms de maneira mais pratica. Estou tentando fazer assim:
Eu faria chamada a esta procedure assim:
Esta tudo funcionando porem esta verificação na minha procedure:
Nao esta funcionando, se eu chamar a procedure tres vezes .... tres vezes o form é aberto. Teria como resolver este problema??
Fico no aguardo.
Tenho uma aplicação onde uso Forms do tipo fsMDIChild
Entao para dar uma agilizada no trabalho gostaria de criar uma Procedure para criar os Forms de maneira mais pratica. Estou tentando fazer assim:
procedure Abre_Form_MDI( pTform : TFormClass; pForm : TForm ); begin if pForm = nil then begin Application.CreateForm( pTform, pForm ); pForm.Show; end; end;
Eu faria chamada a esta procedure assim:
procedure TForm1.Cliente1Click(Sender: TObject); begin Abre_Form_MDI( TForm2, Form2 ); end;
Esta tudo funcionando porem esta verificação na minha procedure:
if pForm = nil then begin
Nao esta funcionando, se eu chamar a procedure tres vezes .... tres vezes o form é aberto. Teria como resolver este problema??
Fico no aguardo.
Mmoreira
Curtidas 0
Respostas
Tnaires
27/12/2006
Olá
Para dar certo, você precisa atribuir [b:e906b99230]nil[/b:e906b99230] à variável que referencia o form assim que você o destruir. Porque, apesar do form ser destruído, a variável continua armazenando o endereço de memória no qual ele estava armazenado.
Abraços
Para dar certo, você precisa atribuir [b:e906b99230]nil[/b:e906b99230] à variável que referencia o form assim que você o destruir. Porque, apesar do form ser destruído, a variável continua armazenando o endereço de memória no qual ele estava armazenado.
Abraços
GOSTEI 0
Mmoreira
27/12/2006
tnaires,
Não entendi sua colocação, sera que voce poderia detalhar?
Não entendi sua colocação, sera que voce poderia detalhar?
GOSTEI 0
Tnaires
27/12/2006
OK
Quando você cria um form utilizando Application.CreateForm, você passa a classe do Form e a referência ( variável ) que o armazenará, certo?
A referência armazena o endereço de memória no qual o formulário está localizado. Quando você libera o formulário da memória, você destrói o objeto de fato, mas a variável continua apontando pra aquele endereço da memória que continha o formulário.
[b:564b17b224]Nil[/b:564b17b224] é uma constante do Delphi que pode ser associada a qualquer ponteiro ou referência. Quando uma referência aponta pra nil, na verdade não aponta pra nenhum endereço de memória.
Ou seja, para seu código dar certo, você tem que atribuir nil à variável que armazena o seu form quando você o destruir. Para isso, coloque sempre no OnClose dos seus forms:
Onde Form1 é a referência ao form.
Lembre-se, isso não destrói o form! Para liberar o form da memória, use o método Release.
Outros colegas do fórum poderão corrigir algo que eu disse, ou complementar as informações.
Abraços
Quando você cria um form utilizando Application.CreateForm, você passa a classe do Form e a referência ( variável ) que o armazenará, certo?
A referência armazena o endereço de memória no qual o formulário está localizado. Quando você libera o formulário da memória, você destrói o objeto de fato, mas a variável continua apontando pra aquele endereço da memória que continha o formulário.
[b:564b17b224]Nil[/b:564b17b224] é uma constante do Delphi que pode ser associada a qualquer ponteiro ou referência. Quando uma referência aponta pra nil, na verdade não aponta pra nenhum endereço de memória.
Ou seja, para seu código dar certo, você tem que atribuir nil à variável que armazena o seu form quando você o destruir. Para isso, coloque sempre no OnClose dos seus forms:
Form1 := nil;
Onde Form1 é a referência ao form.
Lembre-se, isso não destrói o form! Para liberar o form da memória, use o método Release.
Outros colegas do fórum poderão corrigir algo que eu disse, ou complementar as informações.
Abraços
GOSTEI 0
Mmoreira
27/12/2006
tnaires,
Estou usando a procedure:
Para criar o Form2, tenho nos enventos deste Form os codigos:
O meu problema é que mesmo o Form2 ja estando criado se eu executar a procedure -
- o sistema cria novamente o Form2 ... e vai criando quantas vezes eu a chamar. O meu problema na verdade é que quando eu faço a verificação:
Não esta funcionando
Estou usando a procedure:
procedure TForm1.Cliente1Click(Sender: TObject); begin Abre_Form_MDI( TForm2, Form2 ); end;
Para criar o Form2, tenho nos enventos deste Form os codigos:
procedure TForm2.FormDestroy(Sender: TObject); begin Form2 := nil; end;
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; end;
O meu problema é que mesmo o Form2 ja estando criado se eu executar a procedure -
Abre_Form_MDI( TForm2, Form2 );
- o sistema cria novamente o Form2 ... e vai criando quantas vezes eu a chamar. O meu problema na verdade é que quando eu faço a verificação:
if pForm = nil then begin
Não esta funcionando
GOSTEI 0
Mmoreira
27/12/2006
tnaires,
Se voce tiver um tempo da uma olhada neste exemplo e vai ver o que esta acontecendo:
http://www.sendspace.com/file/c7b2qp
Se voce tiver um tempo da uma olhada neste exemplo e vai ver o que esta acontecendo:
http://www.sendspace.com/file/c7b2qp
GOSTEI 0
Macario
27/12/2006
Olá [b:b20dea39b6]mMoreira[/b:b20dea39b6], tranquilo?
Então veja da seguinte maneira :arrow: :
[b:b20dea39b6]procedure Abre_Form_MDI( pTform : TFormClass; pForm : TForm );
begin
if not Assigned(pForm) then
Application.CreateForm( pTform, pForm );
pForm.Show;
end;[/b:b20dea39b6]
Esper que ajude. 8)
Então veja da seguinte maneira :arrow: :
[b:b20dea39b6]procedure Abre_Form_MDI( pTform : TFormClass; pForm : TForm );
begin
if not Assigned(pForm) then
Application.CreateForm( pTform, pForm );
pForm.Show;
end;[/b:b20dea39b6]
Esper que ajude. 8)
GOSTEI 0
Mmoreira
27/12/2006
Macario,
Fiz a mudança sugerida por voce:
Aconteceu o mesmo problema!!
Fiz a mudança sugerida por voce:
procedure Abre_Form_MDI( pTform : TFormClass; pForm : TForm ); begin if not Assigned(pForm) then begin Application.CreateForm( pTform, pForm ); pForm.Show; end; end;
Aconteceu o mesmo problema!!
GOSTEI 0
Macario
27/12/2006
Olá.
Eu faço uso do Assigned para criar meus Forms, mas pelo visto isto não funciona com Forms do tipo fsMDIChild.
Eu faço uso do Assigned para criar meus Forms, mas pelo visto isto não funciona com Forms do tipo fsMDIChild.
GOSTEI 0
Tnaires
27/12/2006
O Assigned verifica justamente se o ponteiro aponta pra nil. O help do Delphi sugere que
e
é a mesma coisa. Se não for, alguém poderia apresentar as diferenças?
mMoreira, vi seu projeto e achei o problema.
Quando você cria o primeiro form, seu endereço é armazenado na variável.
Quando você cria o segundo form, a variável contém o endereço do primeiro form, que está sendo exibido na tela. Ou seja, a condição pForm = nil nunca vai ser verdadeira enquanto você tiver alguma outra instância do mesmo form sendo mostrada na tela.
Possíveis soluções:
- escrever uma rotina que percorra todos os forms abertos e verifique se não existe alguma outra instância dele já criada;
- utilizar forms SDI ( modais ).
Abraços
if Assigned(Ponteiro)
e
if Ponteiro = nil
é a mesma coisa. Se não for, alguém poderia apresentar as diferenças?
mMoreira, vi seu projeto e achei o problema.
Quando você cria o primeiro form, seu endereço é armazenado na variável.
Quando você cria o segundo form, a variável contém o endereço do primeiro form, que está sendo exibido na tela. Ou seja, a condição pForm = nil nunca vai ser verdadeira enquanto você tiver alguma outra instância do mesmo form sendo mostrada na tela.
Possíveis soluções:
- escrever uma rotina que percorra todos os forms abertos e verifique se não existe alguma outra instância dele já criada;
- utilizar forms SDI ( modais ).
Abraços
GOSTEI 0
Fortaum
27/12/2006
- Olá... experimente isso após fechar o form:
FreeAndNil(NomedoForm);
sds!
FreeAndNil(NomedoForm);
sds!
GOSTEI 0
Tnaires
27/12/2006
Possíveis soluções:
- escrever uma rotina que percorra todos os forms abertos e verifique se não existe alguma outra instância dele já criada;
- utilizar forms SDI ( modais ).
Caro mMoreira, se você quer exibir apenas um form de cada vez, porque você tá usando MDIChild?
GOSTEI 0
Macario
27/12/2006
Acredito que seja por facilidade tipo:
Acessar o Cadastro de Cliente e tambem o Cadastro de Fornecedor ao mesmo tempo por exemplo.
Mas não quer que se tenha mais de um cadastro de cliente aberto.
Acessar o Cadastro de Cliente e tambem o Cadastro de Fornecedor ao mesmo tempo por exemplo.
Mas não quer que se tenha mais de um cadastro de cliente aberto.
GOSTEI 0
Mmoreira
27/12/2006
É isso mesmo pela facilidade de poder trabalhar com varias telas de cadastro ao mesmo, poder alternar entre as telas.
Agora pessoal vejam isso:
Criando os Forms atravez da minnha procedure que esta assim:
Chamei a procedure 3 vezes ... ou seja criei o mesmo Form 3 vezes. Ai no Form1 eu estou fazendo isso:
Eu tenho tres mensagens:
1 - Form2_1
2 - Form2_2
3 - Form2
O nome esta sendo alterado por isso minha condição nao funciona
Agora pessoal vejam isso:
Criando os Forms atravez da minnha procedure que esta assim:
if pForm = nil then begin Application.CreateForm( pTform, pForm ); pForm.Show; end;
Chamei a procedure 3 vezes ... ou seja criei o mesmo Form 3 vezes. Ai no Form1 eu estou fazendo isso:
procedure TForm1.nomes1Click(Sender: TObject); var i : integer; begin for i := 0 to MDIChildCount - 1 do begin ShowMessage( MDIChildren[i].Name ); end; end;
Eu tenho tres mensagens:
1 - Form2_1
2 - Form2_2
3 - Form2
O nome esta sendo alterado por isso minha condição nao funciona
GOSTEI 0
Tnaires
27/12/2006
Mas não quer que se tenha mais de um cadastro de cliente aberto.
Ah sim, entendi.
O nome esta sendo alterado por isso minha condição nao funciona
A qual condição você está se referindo? A comparação com nil?
GOSTEI 0
Mmoreira
27/12/2006
tnaires,
Nao estava me referindo ao nil, na verdade eu acabei falando besteira dei uma viajada legal!!! Ja estou ficando doido com isso. De acordo com o que voce disse uma solução seria verificar quais forms estao abertos e fazer a comparação para saber se poderia ou nao ser criado o form.
Um colega aqui do forum me passou um dodigo mas o mesmo deveria ficar na unit principal do aplicativo. O codigo dele ficou assim:
Função para sazer se o form ja existe:
Procedure que vai criar o Form:
Chamada a procedure:
Tudo certo ... apesar de estar funcionando perfeitamente nao me atende 100¬ pois eu gostaria de deixar isso em uma Unit de funcoes de sistema que tenho com varias outras. Entao para contornar isso eu alterei o codigo desta maneira entao ficou tudo na minha Unit de funcoes:
Função para sazer se o form ja existe:
Procedure que vai criar o Form:
Chamada a procedure:
procedure TForm1.Cliente1Click(Sender: TObject);
begin
Abre_Form_MDI( TForm2, Form2, Form1 );
end;
Entao é isso ai, para evitar que ficasse na unit principal do sistema tive que passar como parametro o Form1 que tem sua propriedade:
Nao estava me referindo ao nil, na verdade eu acabei falando besteira dei uma viajada legal!!! Ja estou ficando doido com isso. De acordo com o que voce disse uma solução seria verificar quais forms estao abertos e fazer a comparação para saber se poderia ou nao ser criado o form.
Um colega aqui do forum me passou um dodigo mas o mesmo deveria ficar na unit principal do aplicativo. O codigo dele ficou assim:
Função para sazer se o form ja existe:
function TForm1.FormAberto(AForm: TFormClass): Boolean; var i: Integer; begin Result := false; for I := 0 to MDIChildCount - 1 do if MDIChildren[i].ClassType = AForm then begin Result := true; Break; end; end;
Procedure que vai criar o Form:
procedure TForm1.Abre_Form_MDI( pTform : TFormClass; pForm : TForm ); begin if FormAberto(pTform) then Exit else begin Application.CreateForm( pTform, pForm ); pForm.Show; end; end;
Chamada a procedure:
procedure TForm1.Cliente1Click(Sender: TObject); begin Abre_Form_MDI( TForm2, Form2 ); end;
Tudo certo ... apesar de estar funcionando perfeitamente nao me atende 100¬ pois eu gostaria de deixar isso em uma Unit de funcoes de sistema que tenho com varias outras. Entao para contornar isso eu alterei o codigo desta maneira entao ficou tudo na minha Unit de funcoes:
Função para sazer se o form ja existe:
function FormAberto(AForm: TFormClass; pForm_Principal : TForm): Boolean; var i: Integer; begin Result := false; for I := 0 to pForm_Principal.MDIChildCount - 1 do if pForm_Principal.MDIChildren[i].ClassType = AForm then begin Result := true; Break; end; end;
Procedure que vai criar o Form:
procedure Abre_Form_MDI( pTform : TFormClass; pForm_Cria, pForm_Principal : TForm ); begin if FormAberto(pTform, pForm_Principal) then Exit else begin Application.CreateForm( pTform, pForm_Cria ); pForm_Cria.Show; end; end;
Chamada a procedure:
procedure TForm1.Cliente1Click(Sender: TObject);
begin
Abre_Form_MDI( TForm2, Form2, Form1 );
end;
Entao é isso ai, para evitar que ficasse na unit principal do sistema tive que passar como parametro o Form1 que tem sua propriedade:
Form1.FormSyle := fsMDIForm Acho que nao da para simplificar isso ai mais .... ou será que dá ???? De qualquer forma fica ai meu agradecimento a todos que me ajudaram. Valewww!!
GOSTEI 0