Erro ao chamar MDIChild

08/06/2005

0

Oi gente!

É a primeira vez que estou usando MDIFrom e MDIChild.
O MDIForm é o primeiro a ser criado na aplicação. Só que qdo chamo qualquer outro form configurado como MDIChild o delphi retorna o seguinte erro:

´CANNOT CREAT FORM. NO MDI FORMS ARE CURRENTLY ACTIVE´

Tem algum segredo ou propriedade especial pra usar esse esquema?


Michelle

Michelle

Responder

Posts

08/06/2005

Marco Salles

Tem algum segredo ou propriedade especial pra usar esse esquema?


Tem alguns detalhes , mas como vce esta chamando esse formularios
Filhos.. Qual é o seu código para a criação e para destruição dos formulários filhos :?: :?: :?:

Poderia postar :?: :?:


Responder

09/06/2005

Sérgio Gobbo

Eu faço assim:
Não crio os filhos automaticamente (Project/Options - tira ele do auto-create)
No menu do formulario pai, ao inves de chamá-lo com show, crio ele: Application.CreateForm(TForm1,form1); - tem que colocar o nome da unit no uses do pai tb
No evento OnClose do filho, vc destrói ele com:
Action:=caFree;
form1:=nil;
E é claro, não esquecer de colocar a propriedade formstyle do filho como child, claro.

Acho q se vc fizer assim dará certo.

FLLW


Responder

09/06/2005

Michelle

Eu faço assim: Não crio os filhos automaticamente (Project/Options - tira ele do auto-create) * Jú, se me permite a liberdade de chamá-lo assim, tenho outra dúvida: o form pai tem que, necessariamente, ser criado no auto create? Isso porque, fiz o seguinte teste: - Em uma nova aplicação só coloquei dois forms, frMDIForm e fr MDIchild e ao chamar o filho da maneira citada por vc abaixo, não deu erro algum com o pai sendo criado no auto-create. A questão é que na aplição em questão meu formulário pai só é criado depois de 2 outros formulários e está sendo criado no evento onclick do formulário antecessor da mesma maneira abaixo. Acho que aí é que está o problema pois o erro gerado pelo delphi diz que não pode criar o form filho pois não existe form pai ativo. É isso mesmo? No menu do formulario pai, ao inves de chamá-lo com show, crio ele: Application.CreateForm(TForm1,form1); - tem que colocar o nome da unit no uses do pai tb No evento OnClose do filho, vc destrói ele com: Action:=caFree; form1:=nil; E é claro, não esquecer de colocar a propriedade formstyle do filho como child, claro. Acho q se vc fizer assim dará certo. FLLW



Responder

09/06/2005

Marco Salles

A questão é que na aplição em questão meu formulário pai só é criado depois de 2 outros formulários e está sendo criado no evento onclick do formulário antecessor da mesma maneira abaixo.


:idea: :idea:
Uma tentativa que em muitas situaçoes da certo serai alterar tb o FormStyle dos outros dois formulários que antecede o Formulafio em questão

Assim fazer

FormAntecessor.FormStyle:=fsMDIForm;

:arrow: [b:2e18d4cee5]Nesta situação voce pode deixar as coisas como estão[/b:2e18d4cee5] :
A questão é que na aplição em questão meu formulário pai só é criado depois de 2 outros formulários e está sendo criado no evento onclick do formulário antecessor da mesma maneira abaixo.


Acho que o junior_gobbo não vai importar de voce chama-lo assim:
Jú, se me permite a liberdade de chamá-lo assim

Ele vai ater gostar , eu acho......Se voce eu , eu gostaria :lol: :lol:


Responder

09/06/2005

Massuda

[quote:15d6d94027=´Marco Salles´]
A questão é que na aplição em questão meu formulário pai só é criado depois de 2 outros formulários e está sendo criado no evento onclick do formulário antecessor da mesma maneira abaixo.

...
alterar tb o FormStyle dos outros dois formulários que antecede o Formulafio em questão para

FormAntecessor.FormStyle:=fsMDIForm;[/quote:15d6d94027]Talvez isso não funcione. Um aplicativo MDI só pode ter um form ativo com estilo fsMDIForm (afinal, esse [b:15d6d94027]é[/b:15d6d94027] o form principal do programa).

A abordagem correta seria (auto)criar o form principal primeiro.

Provavelmente esses dois forms que hoje são criados primeiro podem sem problemas ser criados no OnCreate do form principal (especialmente se forem para login, splash window, etc). Um tópico similar está [url=http://www.forumweb.com.br/foruns/index.php?showtopic=29730]aqui[/url]


Responder

09/06/2005

Marco Salles

--------------------------------------------------------------------------------

Marco Salles escreveu: Michelle escreveu: A questão é que na aplição em questão meu formulário pai só é criado depois de 2 outros formulários e está sendo criado no evento onclick do formulário antecessor da mesma maneira abaixo. ... alterar tb o FormStyle dos outros dois formulários que antecede o Formulafio em questão para


Massuda escreveu
FormAntecessor.FormStyle:=fsMDIForm; Talvez isso não funcione. Um aplicativo MDI só pode ter um form ativo com estilo fsMDIForm (afinal, esse é o form principal do programa).


Massuda, voce esta coberto de razão ,no que toca o conceito.. Eu esqueci de colocar o conceito..

[b:67d8709046]A abordagem correta seria (auto)criar o form principal primeiro[/b:67d8709046]


... Mas funcionar , pode acreditar, que talvez funcione....Faça um teste.


Responder

09/06/2005

Michelle

Acho que o junior_gobbo não vai importar de voce chama-lo assim:


Marquinho (só pra vc não ficar com ciúme), valeu a atenção!
Vi que essa questão já foi bastante discutida no fórum e que na maioria das vezes ninguém apresentou um código funcional.
No meu caso, a dificuldade é a seguinte:
meu primeiro form a ser startado pela aplicação, é um form que contém vários alíases, pois o sistema que desenvolvi aqui na empresa onde trabalho, permiti ao usuário acessar a base de dados do cliente desejado antes de iniciar o programa.
Selecionada a base desejada, é a vez de startar um splash de abertura que fica ativo enqto, paralelo a ele, meu form DataModule tb é criado e a base de dados escolhida é carregada.
Depois da base carregada entra o form de login pra só então entrar o form principal que é o meu MDI form.

Complicado? Ai, tomara que esteja sendo clara. Não sou muito boa nisso!

Bjinho


Responder

09/06/2005

Marco Salles

Olha so...

[b:62deaa6250]Como o massuda disse,[/b:62deaa6250]

Crie o Form principal primeiro .....


(Project/Options - coloque ele do auto-create)...

Apresente o form com o aliase primeirO.. eu acho que basta colocar este form antes no projeto assim:::

   Application.Initialize;
   Application.CreateForm(TForm2, Form2); //form com o aliase
                                                             //Outros forms
   Application.CreateForm(TForm1, Form1);
  Application.Run;


Por ultimo depos da senha e so apresentar o Formprincipal ao inves de cria-lo...

Vi que essa questão já foi bastante discutida no fórum e que na maioria das vezes ninguém apresentou um código funcional.


As pessoas apresentam sim , so que muitas das vezes é dificil entender o que realmente se esta passando...

Quando dá errado , não se pode desistir..Quando da certo tem que postar dando Ok.. Muitas pesoas abandonan o tópico, ficando todo mundo sem saber se foi resolvido ou se a pessoa desistiu.. Com isto não se evolui :cry: :cry:

Boa sorte...


Responder

09/06/2005

Michelle

Crie o Form principal primeiro ..... (Project/Options - coloque ele do auto-create)... Apresente o form com o aliase primeirO.. eu acho que basta colocar este form antes no projeto assim:::
   Application.Initialize;
   Application.CreateForm(TForm2, Form2); //form com o aliase
                                                             //Outros forms
   Application.CreateForm(TForm1, Form1);
  Application.Run;
Por ultimo depos da senha e so apresentar o Formprincipal ao inves de cria-lo... Boa sorte...


Depois de seguir os passos acima, o erro continuou sendo gerado, então mudei a propriedade dos forms que devem abrir antes do Principal para MDI form e o erro parou de ser gerado.
Só que agora o problema é que ele cria os forms MDIchild, mas não mostra os mesmos na tela. Isso acontece qdo chamo os MDI Child com o comando Show. Já qdo uso ShowModal gera o erro ´Cannot make visible window´.
Ninguém merece, né!? Tem alguma sugestão?


Responder

09/06/2005

Marco Salles

Ninguém merece, né!?


quem te dize que seria fácil...

Vamos fazer o seguinte...

Deixar os form asntes do principal com a propriedade FormSttle:=fsNormal
Deixar o FormPrincipal com a Propriedade
FormSttle:=fsMDIForm
Como era antes...

[b:667ba15744]coloque o formPrincipal para ser criado automaticamente (Project/Options - do auto-create)..Agora inverta a ordem na criação[/b:667ba15744]

A Diferença vem agora

Application.Initialize;
Application.CreateForm(TForm2, Form2); // FormPrincipal vem antes
// Outros forms .. etc...
Application.CreateForm(TForm1, Form1);
form1.Show;
Application.Run;

se voce não for usar mais os form que antecedem o formPrincipal , voce deve destri-los...Acho que pode ser feito na própia chamada

por exemplo

procedure TFormAtual.Button1Click(Sender: TObject);
begin
FormPrincipal.Show;
freeandnil(formatual); 
end;


Assim voce libera memoria.. Mas esta parte é melhor pedir a opinião do massuda, ele e teorico e pode orientar a melhor maneira de voce liberar estes forms caso voce não os utilize mais

Durante esse passos , os form são apresentados e os anteriores destruidos...

Ate que o ultimo form de login , apos a validação da senha , chama o formPrincipal e consequentemente se autoDestroe, digamos assim

procedure TFormLogin.Button1Click(Sender: TObject);
begin
se senha correta
begin
  FormPrincipal.Show;
  freeandnil(formaLogin); 
end
else
  application.terminate;
end;




Obs::: O Unico incoveniente desse modo e que o form principal , mesmo que ele não fique imediatamente ativo, ele ainda esta visivel e pode ser acessado.. Então sugiro que estes forms anteriormente criados tenham algumas propriedades que irão minimizar e impedir que isto venha a ocorrer

1)No evento onshow deles escreva o seguinte código:
 DeleteMenu(GetSystemMenu(Handle, False), SC_MOVE, MF_BYCOMMAND);//Nao deixa arrastar o form


2) Não deixe propriedade que permitem minimizar estes forms.. 
No objecto inspector va em BorderIcons e escolha BiMiniminize e BiMaximize cetado em false...


3) No evento onclose desses formulários que antecedem o Principal
escrever o seguinte...
application.terminate;


Note que fechar é diferente de destruir

4) Note que a posição e o tamanho desse form que antecedem o Formulário Principal, deve ser cuidadosamenente estudado , para não dar um efeito visual desagradavel


5)Dica.. como o form de login geralmente é  é pequeno , sugiro que ele seje parte de outro form, se quiser de passo uma dica show para criaçõa desse form de login


6) porque to preocupado com essas dicas... Rode a aplicação sem esse passos e voce ira perceber que com oo formPrincipal foi criado , voce podera acessa-lo .. ja que  o formularios anteriores , não podem ser criados na formashowmodal


7) Todas esses passos puderiam ser evitados se voce estivesse trabalhando com o modo clássico na criação e destruição dos formulário MDI...


8) Acho que não to esquecendo de nada eu ..To sem o delphi aqui para testar :cry: :cry: :cry: .. Mas amanha voce testa e comunique os posíveis erros.. .. :cry: :cry: :cry:

boa sorte...

:cry:


Responder

10/06/2005

Sérgio Gobbo

Para fazer isso, sem que o form principal fique aparecendo, faça o seguinte: (já testei)

faça como o Marco Salles disse, e crie primeiro o form principal: (para isso, vá em View/Project Manager, clique com o botão direito no nome do projeto, Project1.exe por exemplo, e escolha View Source)

begin
Application.Initialize;
Application.CreateForm(TForm2, Form2); //este seria o form principal, MDIForm
Application.CreateForm(TForm1, Form1);//form da tela de splash
form1.showmodal;// com esse showmodal o form pai (MDIForm) não aparecerá
Application.Run;
end.

Como o form1 é a tela de splash, ele não precisa ter barra de titulo (propriedade BorderStyle deve ser bsNone). Sem a barra de titulo o botão fechar não aparece, não deixando o usuario fechá-lo (pois caso ele fechasse, o form1 (pai) apareceria)
No evento q faz a tela de splash sumir, você programa:

form2.show;
form1.close;

Depois programe no OnCreate do Form Principal (pai) a destruição e liberação de memória do form1 fechado a pouco:

freeandnil(form1);

Pronto, desta maneira o 1º form a aparecer seria o da tela de splash e o form pai não apareceria enquanto o splash estivesse aparecendo, e o pai seria o principal, evitando o erro na hora de criar os forms filhos.

No caso da tela de login, vc tanto poderia chama-la após o splash ser descarregado, mas aí destruindo o splash no onCreate do form login e destruindo o form login no OnCreate do Pai; como poderia chamar o form de login dentro do pai, como form filho, e de acordo com o usuario, habilitar apenas oq este pode acessar do sistema.

Espero ter podido te ajudar Mi (hehe)

T+


Responder

10/06/2005

Marco Salles

ju para lá Mi para cá , isto ja esta virando amizade e to vendo que vou ser o padrinho...

Mas vamos lá :

Duas coisas que gostaria que voce revisse....

Eu não sei com voce definiu a propriedade formSytle desses formulários ,
que antecedem ao formulário Principal....Mas se não me engano a Intrução
form1.showmodal;// com esse showmodal o form pai (MDIForm) não aparecerá

Da erro...
Por isto que eu disse anteriormente :::
ja que o formularios anteriores , não podem ser criados na formashowmodal


a segunda , e o seguinte .. Voce esta destruindo os formsecuncadários , logo no oncreate do formPrincipal... Este form é o primeiro a ser criado e portando a instrução
freeandnil(form1);

Não tera o efeito desejado... Erro na execução , não acredito , pois esta instrução testa antes de destruir , mas como esses formulários ainda não foram criados , ele simplesmente não os destroi

Isto são apenas conjunturas.. E devem ser levados com o intuito de somar. So isso.


Responder

11/06/2005

Sérgio Gobbo

[quote:06ec27d44c=´Marco Salles´]
Eu não sei com voce definiu a propriedade formSytle desses formulários ,
que antecedem ao formulário Principal....Mas se não me engano a Intrução
[/quote:06ec27d44c]

O formstyle dos antecessores ao pai estão como fsNormal

Citação: form1.showmodal;// com esse showmodal o form pai (MDIForm) não aparecerá Da erro...


Não dá erro não, já testei e funcionou perfeitamente.

a segunda , e o seguinte .. Voce esta destruindo os formsecuncadários , logo no oncreate do formPrincipal... Este form é o primeiro a ser criado e portando a instrução [quote:06ec27d44c]freeandnil(form1);

Não tera o efeito desejado... Erro na execução , não acredito , pois esta instrução testa antes de destruir , mas como esses formulários ainda não foram criados , ele simplesmente não os destroi
[/quote:06ec27d44c]

Neste caso eu me equivoquei, com a instrução no Oncreate, não apresenta erro, porém realmente não destrói.
No caso não sei onde por esta instrução, pois colocando-a no evento close do secundário, ou no show do pai, apresenta erro.
Sendo apenas 1 form secundario, poderia-se deixa sem destruir mesmo, pois ficaria funcional e de acordo com a descrição.

ju para lá Mi para cá , isto ja esta virando amizade e to vendo que vou ser o padrinho...


hehe... se ela topar...

T+


Responder

14/06/2005

Michelle

Oi!

Desculpem-me por não ter respondido antes. Meu final de semana foi um tumulto e ontem meu chefe iniciou a segunda feira com uma disposiçào assustadora.
Bom, mas agora estou mais sossegada e venho através deste dar a feliz notícia de que finalmente deu tudo certo.
Graças as dicas de vcs, organizei minhas idéias e consegui fazer o que queria.
Os passos foram:

1º) Forms antecessores ao frPrincipal -> FormStyle=fsNormal;
Form Principal-> FormStyle=MDIform;
Forms Filhos-> FormStyle=MDIChild;

2º) Form frPrincipal único indicado para criaçào automática -> (Project / Options/ Auto-Create forms);

3º) O segredo é realmente destruir e liberar todos os forms ancestrais (profundo né!?) ao frPrincipal no momento da criação de qualquer frFilho, garantindo neste momento que o único form ativo seja o frPrincipal;

4º) Estava pecando num detalhe: dependia de informações atreladas à alguns componentes pertencentes aos forms antecessores. O que me impedia de destruir realmente esses forms. Passei toda a informaçào para variáveis e matrizes públicas e resolvi essa questão.

Daí organizei a criação dos meus forms da seguinte maneira:

Em (Project-> View Source):

Application.CreateForm(TfrmPrincipal, frmPrincipal);
Application.Initialize;
Application.Name:= ´Teste MDI´;
Application.Title := ´MDI´;
Application.CreateForm(TfrmSeleAlias, frmSeleAlias);
frmSeleAlias.ShowModal;
Application.CreateForm(TfrmEntrada, frmEntrada);
frmEntrada.Show;
Application.CreateForm(TDM, DM);
frmEntrada.Hide;
frmEntrada.Free;
Application.CreateForm(TfrmSenhaAcesso, frmSenhaAcesso);
frmSenhaAcesso.ShowModal;
Application.Run;

procedure TfrmSeleAlias.BitBtn1Click(Sender: TObject);
begin
alias:=combobox1.Text;
frmSeleAlias.Close;
end;

procedure TfrmSeleAlias.FormClose(Sender: TObject;
var Action: closeAction);
begin
action:=cafree;
FrmSeleAlias:=Nil;
end;

O mesmo valeu pro restante dos forms iniciais. Dando o comando Close no evento OnClick e realizando a destruição e liberação no OnClose.

Agora a aplicaçào está redondinha. A não ser pelo fato de que ao abrir vários forms filhos e depois mandar organizar a janela com os comandos:
Cascade, tilemode:=tbhorizontal, tilemode:=tbvertical e arrangeicons, os forms minimizam ficando parcialmente visíveis, mas sem poder aumentar o tamanho deles e nem manipulá-los como se tivessem sido organizados pelo excell por exemplo.

Mas acho que já estou abusando né!?

Valeu mais uma vez pela paciência de vcs.

Ah, e sobre a questão:

Virando amizade...padrinho ... se ela topar...


gostaria de pronunciar que: ´Já estou envolvida! Se o Jú pular... tb pulo!´ (plagiei do Leo di Caprio em Titanic).

Só pra descontarir tá!?

Bjos pra vcs! Até a próxima! :P


Responder

14/06/2005

Marco Salles

Bom, mas agora estou mais sossegada e venho através deste dar a feliz notícia de que finalmente deu tudo certo.


ficamos felizes por isto...

Vi que essa questão já foi bastante discutida no fórum e que na maioria das vezes ninguém apresentou um código funcional.


Viu que não é tanto assim....

gostaria de pronunciar que: ´Já estou envolvida! Se o Jú pular... tb pulo!´ (plagiei do Leo di Caprio em Titanic).


Vamos torcer para que o Ju Pule, assim estaremos preparados para te salvar.. Quanto ao ju :?: :?: :?: Quem mandou ele pular. Fazer o que né

Só pra descontarir tá!?



Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar