Erro ao chamar MDIChild
08/06/2005
0
É 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
Posts
08/06/2005
Marco Salles
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 :?: :?:
09/06/2005
Sérgio Gobbo
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
09/06/2005
Michelle
09/06/2005
Marco Salles
: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] :
Acho que o junior_gobbo não vai importar de voce chama-lo assim:
Ele vai ater gostar , eu acho......Se voce eu , eu gostaria :lol: :lol:
09/06/2005
Massuda
...
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]
09/06/2005
Marco Salles
Massuda escreveu
Massuda, voce esta coberto de razão ,no que toca o conceito.. Eu esqueci de colocar o conceito..
... Mas funcionar , pode acreditar, que talvez funcione....Faça um teste.
09/06/2005
Michelle
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
09/06/2005
Marco Salles
[b:62deaa6250]Como o massuda disse,[/b:62deaa6250]
(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...
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...
09/06/2005
Michelle
Application.Initialize; Application.CreateForm(TForm2, Form2); //form com o aliase //Outros forms Application.CreateForm(TForm1, Form1); Application.Run;
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?
09/06/2005
Marco Salles
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:
10/06/2005
Sérgio Gobbo
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+
10/06/2005
Marco Salles
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
Da erro...
Por isto que eu disse anteriormente :::
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
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.
11/06/2005
Sérgio Gobbo
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
Não dá erro não, já testei e funcionou perfeitamente.
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.
hehe... se ela topar...
T+
14/06/2005
Michelle
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:
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
14/06/2005
Marco Salles
ficamos felizes por isto...
Viu que não é tanto assim....
Vamos torcer para que o Ju Pule, assim estaremos preparados para te salvar.. Quanto ao ju :?: :?: :?: Quem mandou ele pular. Fazer o que né
Clique aqui para fazer login e interagir na Comunidade :)