Herança
procedure TfrmConsFuncionarios.btnEditarClick(Sender: TObject);
begin
inherited;//aki nao ta herdando nada ainda nao
inserir := false;//variaveis criadas no form pai
IDCadastro := tabConsulta.fieldByName(´ID´).AsInteger;
// apenas altero as variaveis e crio o form
if not Assigned(frmCadFuncionarios) then
frmCadFuncionarios := TfrmCadFuncionarios.Create(self);
frmCadFuncionarios.ShowModal;
FreeAndNil(frmCadFuncionarios);
end;
e para add um novo funcionario apenas defino inserir=true e crio o form.As variaveis estao no form pai e sao usadas pelo form padrao consulta e cadastro. Quando crio o form cadastro ele excuta esse codigo:
//a tabela foi passada como parametro no formcreate
procedure TfrmMestreCadastro.AbreFormCad;
begin
if inserir Then//variavel usada nos forms conulta e cadastro
begin
tabCadastro.Cancel;//tabCadastro criada no form padrao cadastro
tabCadastro.Append;
tabCadastro.FieldByName(´ID´).AsInteger := GenProximoID(Generator);
end
Else
begin
tabCadastro.Close;
tabCadastro.FetchParams;
tabCadastro.Params.ParamByName(´pID´).AsInteger := IDCadastro;
tabCadastro.Open;
end;
end;
O problema esta nas variaveis INSERIR e IDCadastro,definidas no form pai. Elas deveriam ser alteradas no form consulta,mas,nao é possivel. Ta ai se alguem puder me ajudar!
Ednilson Campos
Respostas
Rodc
08/12/2008
A variável é pública na classe pai?
Ednilson Campos
08/12/2008
Ednilson Campos
08/12/2008
Rodc
08/12/2008
Ednilson Campos
08/12/2008
Ednilson Campos
08/12/2008
Rodc
08/12/2008
Ednilson Campos
08/12/2008
Rodc
08/12/2008
Se você tem Form1 e Form2 descendedo de TForm; ao colocar ´Form1.Visible := false´ não fará com que a variável ´Visible´ do Form2 também esteja como false apenas porque as duas descendem da mesma classe, correto?
Você não consegue chamar frmMestreCadastro.AbreFormCad() porque este formulário não está criado. É a mesma coisa de você tentar acessar uma função de um formulário qualquer (Form1, Form2, ...) que não foi criado ainda.
Ednilson Campos
08/12/2008
Ednilson Campos
08/12/2008
Ednilson Campos
08/12/2008
Discorpio
08/12/2008
Em primeiro lugar quando voce instancia um Form na memória, ao tentar instanciar o mesmo Form com a mesma variável novamente, ele dá o erro de Access Violation......
Isto ocorre porque o mesmo Form já se encontra em memória, voce deve sempre limpá-lo da memória com o método Free ou com a função FreeAndNil(Variável), ai sim voce pode instanciá-lo novamente em uma nova chamada.
Quanto a variáveis Inserir: Boolean, o nosso amigo Rodc está correto, apesar dela estar declarada no Form Ancestral (Pai), ao instanciar os Forms derivados (filhos), cada form filho terá a sua variável Insert com valores diferentes, com já foi dito pelo nosso amigo.
Para resolver esta questão, voce deverá implementar um método Inserir no Form Ancestral (Pai) e neste método atribuir o valor de Insert como True. Ao ser invocado o método Inserir nos Forms filhos, a variável Insert já é configurado automaticamente como True, isto é se você implementar também o método inserir nos forms filhos com a cláusula Inherited.
Ednilson Campos
08/12/2008
procedure TfrmPai.NovoRegistro(ClasseForm: TFormClass;pID: Integer);
var
form : TForm;
begin
Try
application.CreateForm(ClasseForm,form);
inserir := true;//defini como true
tabCadastro.Cancel;//parametro q vem do formCadastro{aki ta dando o erro q vc disse sobre liberar da memoria{Acces Violation}
tabCadastro.Append;
tabCadastro.FieldByName(´ID´).AsInteger := GenProximoID(Generator);
form.ShowModal;
Finally
FreeAndNil(form);
End;
end;
No formulario de consulta chamo dessa forma:
procedure TfrmConsFuncionarios.btnNovoClick(Sender: TObject);
begin
inherited;
NovoRegistro(TfrmCadFuncionarios);//passo a Classe do formCadastro como parametro
end;
Evento quando o formCadastro é criado:
procedure TfrmCadFuncionarios.FormCreate(Sender: TObject);
begin
inherited;
dmCadFuncionarios := TdmCadFuncionarios.Create(Self);
dmCadFuncionarios.cdsCadastro.Open;
//passo os outros parametros{tabela e generator}
tabCadastro := dmCadFuncionarios.cdsCadastro;
Generator := ´GEN_FUNCIONARIOS_ID´;
end;
E e pra Editar tenho este metodo no form Pai:
procedure TfrmPai.Editar(pID: Integer);
var
ID : Integer;
begin
tabCadastro.Close;//aki tbm da o erro{Violaçao de Memoria}
tabCadastro.FetchParams;
tabCadastro.Params.ParamByName(´pID´).AsInteger := ID;
tabCadastro.Open;
end;
o metodo é chamdo da seguinte forma:
procedure TfrmConsFuncionarios.btnEditarClick(Sender: TObject);
begin
inherited;
Editar(tabConsulta.fieldByName(´ID´).AsInteger);//parametro para ediçao tbm nao consegui resolve essa parte
end;
As variaveis q utilizo:
public{todas no form Pai}
tabCadastro,tabConsulta : Tclientdataset;
sqlConsulta : TSQLQuery;
Generator : String;
inserir : Boolean;
pIDCadastro : Integer;
Agora tudo q utilizo ta ai espero q facilite pra vcs me ajudarem!
Discorpio
08/12/2008
Deixa eu te fazer uma pergunta:
Esse form Consulta está herdando do Form Pai :?:
Ednilson Campos
08/12/2008
Micheus
08/12/2008
Entretanto, quando vc utiliza o botão [i:5b9df98b18]btnEditar[/i:5b9df98b18], o seu método [i:5b9df98b18]Editar[/i:5b9df98b18], simplesmente utiliza a variável [i:5b9df98b18]tabCadastro[/i:5b9df98b18] - que estará apontando para onde??? (Sabe-se lá. Esse o motivo do erro logo na primeira linha em que vc a referencia)
Acho que duas observações seriam pertinentes:
1) o [i:5b9df98b18]dmCafFuncionarios[/i:5b9df98b18], assim como o [i:5b9df98b18]frmCadFuncionarios[/i:5b9df98b18], deveria estar sendo liberado da memória - o que não consta do código (talvez, no [i:5b9df98b18]OnDestroy[/i:5b9df98b18] ou [i:5b9df98b18]OnClose[/i:5b9df98b18] do [i:5b9df98b18]frmCadFuncionarios[/i:5b9df98b18] vc esteja fazendo isto, mas não citou)
2) ao usar a opção de edição, pela lógica, vc deveria novamente criar o [i:5b9df98b18]frmCadFuncionarios[/i:5b9df98b18], o que criaria o [i:5b9df98b18]dmCadFuncionarios[/i:5b9df98b18] e inicializaria as variáveis dos datasets, e então, antes de chamar o [i:5b9df98b18]ShowModal[/i:5b9df98b18], posicionaria o dataset no registro desejado.
Abraços
Ednilson Campos
08/12/2008
procedure TfrmPai.Editar(ClasseForm: TFormClass;pID: Integer);
var
form : TForm;
begin
Try
application.CreateForm(ClasseForm,form);
tabCadastro.Close;// aki acontece o erro
tabCadastro.FetchParams;
tabCadastro.Params.ParamByName(´pID´).AsInteger := pID;
tabCadastro.Open;
form.ShowModal;
Finally
FreeAndNil(form);
End;
end;
Ednilson Campos
08/12/2008
Micheus
08/12/2008
Por acaso, nas opções de projeto, vc retirou lembrou de retirar os forms da auto-criação? (ficaria apenas o principal)
Ednilson Campos
08/12/2008
Discorpio
08/12/2008
É como a lei de Murphy que aqui no caso: ´Será que existe algo a mais :?: ´
Sim tem algo ainda mais além do que o nosso Micheus citou, que aliás muito bem observado por ele.
A algo a mais a que me refiro, é que quando voce defini um Form Pai e tantos outros Forms Filhos derivados dele, para instanciar os Forms Filhos, o Form Pai não precisa estar instanciado em memória, isto porque o [color=darkblue:b3f508590f]Delphi define por padrão todos os métodos de uma classe como estáticos[/color:b3f508590f], assim a Form Pai funciona como se fosse um Form biblioteca.
Assim sendo, se voce está instanciando os Forms frmCadastro e frmConsulta, sendo estes os Forms pais de outros tantos, não há essa necessidade.
Caso não esteja fazendo isso, então voltamos ao ponto inicial citado pelo nosso Amigo Micheus, onde no Evento OnCreate do Form Pai voce cita que cria o dmCadastro contendo os DataSets. Portanto voce deve destruí-lo no Evento OnClose deste mesmo Form pai.
Entretanto eu vejo uma solução mais simples do que voce criar dois DataModules (dmCadastro e dmConsuta), pois quanto mais objetos instanciados, mais trabalho para controlá-los e destruí-los.
Qual é a sugestão então :?:
Simples, voce colocar apenas um DataSet e um DataSouce no primeiro Form Pai. Ora se os demais herdam deste Form pai, então vão também herdar o DataSet e o DataSource, onde cada DataSet e cada DataSource será independente em cada Form filho, nesse caso voce pode configurá-lo dentro de cada Form filho para abrir a sua tabela respectiva.
Qual é a vantagem disto. :?:
Pelo menos voce não precisa instaciar um ou dois DataModules, economizando memória, apenas o DataSet em cada Form Filho por ocasião da instanciação deste, além do que voce economiza recursos de contrôle em ter que estar instanciando DataModules e abrindo DataSets e depois fechando DataSets de destruindo DataModules. Valendo lembrar que voce só precisa abrir o DataSet que está em cada Form Filho, no evento OnCreate ou OnShow do Form Pai e fechá-lo no se evento OnClose.
Detalhe, deixe apenas um único DataModule ativo contendo apenas o IBDataBase e o IBTransaction.
Discorpio
08/12/2008
Só agora vi o seu último Post.
Ou voce utiliza Action := caFree;
Ou voce utiliza frmCadFuncionarios := nil;
Os dois juntos é claro que vai dar erro, pois logo na primeira chamada Action := caFree, a instância do Form será limpa, e quando fizer a segunda chamada (frmCadFuncionarios), ele vai limpar o quê :?:
Eu sugiro voce substituir esses dois métodos por FreeAndNil(frmCadFuncionarios) como voce utilizou com o dmCadFuncionarios, assim:
.... FreeAndNil(dmCadFuncionarios) FreeAndNil(frmCadFuncionarios) ...
Ednilson Campos
08/12/2008
procedure TfrmConsFuncionarios.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
inherited;
Action := CaFree;
frmConsFuncionarios := nil;
end;
e para os DataModules assim:
procedure TfrmConsFuncionarios.FormDestroy(Sender: TObject);
begin
inherited;
dmConsFuncionarios.cdsFuncionarios.Close;
FreeAndNil(dmConsFuncionarios);
end;
Agora outra duvida é sobre o DataModule de conexao estar sendo criado automaticamente,fica melhor msm se nao for assim,mas,onde devo instancia-lo no formPricipal ou no Source do projeto? Eu nao estou criando datamodule nos forms Mestres,a cada formulario criado seu respectivo datamodule é criado e liberado,seja de consulta ou de cadastro.
Discorpio
08/12/2008
O DataModule principal que contém o SQLConnection voce pode instanciá-lo no momento da inicialização do seu sistema.
Mas como eu faço isso :?:
Simples.
Vá no menu Project --> Options, voce vai abrir a ferramento ´Project Options for nome do seu projeto e vai encontrar dentro dela uma caixa combobox contendo o nome do Form principal que vai ser aberto logo de início e duas caixas de listagem, uma nominada Auto-Create Forms e Available Forms. O que estiver dentro de Auto-Create Forms é instanciado na inicialização do sistema, portanto, mova para Available Forms todos os Forms que voce não queira que seja instanciado (armazenado em memória) logo quando o seu sistema inicia, neste inclua-se os DataModules de Cadastro e Consulta. Deixe somente em Auto-Create Forms, o DataModule Principal e o Form Principal.
Agora quanto a instanciar os demais DataModules e Forms, voce precisa observar o seguinte:
Em seu primeiro post observei que voce em certas ocasiões está utilizando o método ShowModal desta Forma:
Try application.CreateForm(ClasseForm,form); inserir := true;//defini como true tabCadastro.Cancel; tabCadastro.Append; tabCadastro.FieldByName(´ID´).AsInteger := GenProximoID(Generator); form.ShowModal; Finally FreeAndNil(form); // Aqui voce destroi o Form End;
Ora se voce destroi o esse mesmo Form antes lá dentro do seu Evento OnClose, o que voce acha que vai acontecer com a instrução logo abaixo do ShowModal, isto quando ele tentar destruir o Form que já foi destruído. :?:
Então neste caso coloque tão somente dentro do Evento OnClose de cada Form Cadastro e Consulta, somente a destruição dos DataModules Cadastro e Consulta, assim:
procedure TfrmConsFuncionarios.FormClose(Sender: TObject; var Action: TCloseAction); begin inherited; dmConsFuncionarios.cdsFuncionarios.Close; FreeAndNil(dmConsFuncionarios); end;
E só, descarte totalmente o evento Destroy destes formulários
Ednilson Campos
08/12/2008
Pessoal com a ajuda de vcs tenho corrigido alguns detalhes,muito obrigado! Ainda nao consegui corrigi os principais erros. Desculpa mas fica errado liberar o formulario dessa forma:
procedure TfrmCadFuncionarios.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
inherited;
Action := Cafree;
frmCadFuncionarios := nil;
end;
e por estar liberando o form como fiz acima nao posso liberar como ta logo abaixo
procedure TfrmPai.Editar(ClasseForm: TFormClass;pID: Integer);
var
form : TForm;
begin
Try
application.CreateForm(ClasseForm,form);
tabCadastro.Close;
tabCadastro.FetchParams;
tabCadastro.Params.ParamByName(´pID´).AsInteger := pID;
tabCadastro.Open;
form.ShowModal;
Finally
FreeAndNil(form);//aki com o FreeAndNil(form)?vcs ja falaram mas sempre achei q fosse necessario fazer assim e tbm ja corrigi to so confirmando
End;
end;
e tbm liberar o datamodule de cadastro dessa forma:
procedure TfrmCadFuncionarios.FormDestroy(Sender: TObject);
begin
inherited;
dmCadFuncionarios.cdsCadastro.Close;
FreeAndNil(dmCadFuncionarios);
end;
Estou isntanciando o datamodule principal no form principal retirei do auto create:
procedure TfrmPrincipal.FormCreate(Sender: TObject);
begin
if not Assigned(dmPrincipal) then
dmPrincipal := TdmPrincipal.Create(Application);
end;
e liberando no OnClose
procedure TfrmPrincipal.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
inherited;
dmPrincipal.sqlconPrincipal.Connected := False;
FreeAndNil(dmPrincipal);
end;
Tem algo mais q posso fazer sobre o dmPrincipal,nao ta ando erro.
Agora o q resta msm é o formulario de cadastro q ao ser criado e Editando ou Inserindo ainda da erro na linha especificada abaixo::
procedure TfrmPai.Editar(ClasseForm: TFormClass;pID: Integer);
var
form : TForm;
begin
Try
application.CreateForm(ClasseForm,form);
tabCadastro.Close;//aki violaçao de memoria{esse parametro vem do formCadFuncionarios no evento OnCreate}
tabCadastro.FetchParams;
tabCadastro.Params.ParamByName(´pID´).AsInteger := pID;
tabCadastro.Open;
form.ShowModal;
Except
End;
end;
Ednilson Campos
08/12/2008
Estou liberando o DataModule no Evento OnClose como fui aconselhado:
procedure TfrmConsFuncionarios.FormClose(Sender: TObject; var Action: TCloseAction); begin inherited; dmConsFuncionarios.cdsFuncionarios.Close; FreeAndNil(dmConsFuncionarios); end;
e agora os metodos Editar e Inserir estao assim:
procedure TfrmPai.Editar(ClasseForm: TFormClass;pID: Integer);
var
form : TForm;
begin
Try
application.CreateForm(ClasseForm,form);
tabCadastro.Close;{o erro de violaçao de memoria continua}
tabCadastro.FetchParams;
tabCadastro.Params.ParamByName(´pID´).AsInteger := pID;
tabCadastro.Open;
form.ShowModal;
Finally
FreeAndNil(form);
End;
end;
procedure TfrmPai.NovoRegistro(ClasseForm: TFormClass);
var
form : TForm;
begin
Try
application.CreateForm(ClasseForm,form);
tabCadastro.Cancel;{o erro de violaçao de memoria continua}
tabCadastro.Append;
tabCadastro.FieldByName(´ID´).AsInteger := GenProximoID(Generator);
form.ShowModal;
Finally
FreeAndNil(form);
End;
end;Ao liberar um formulario com FreeAndNil(form) nao é preciso liberar tbm no OnClose correto?
Os parametros vem do Evento OnCreate como disse antes:
procedure TfrmCadFuncionarios.FormCreate(Sender: TObject); begin inherited; dmCadFuncionarios := TdmCadFuncionarios.Create(Self); dmCadFuncionarios.cdsCadastro.Open; tabCadastro := dmFuncionarios.cdsFuncionarios; Generator := ´GEN_FUNCIONARIOS_ID´; end;
Seria errado fazer herança com DataModule assim:
pq assim a manutençao seria mais facil. Codigos como esse por ex ficaria apenas no TdmMestreCadastro:
procedure TdmCadastro.dspCadastroBeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean); begin if UpdateKind = ukInsert then if SourceDs = qryCadastro then Begin qryGen.Open; try DeltaDS.FieldByName(´ID´).NewValue := qryGen.FieldByName(´NOVO_ID´).Value; cdsCadastro.Edit; cdsCadastro.FieldByName(´ID´).Text := DeltaDS.FieldByName(´ID´).AsString; finally qryGen.Close; end; end; end;
Mas no momento a prioridade é fazer funcionar o Cadastro!
Valew t+!!![quote:80019f5fb2][/quote:80019f5fb2]
Ednilson Campos
08/12/2008
Obrigado!
Discorpio
08/12/2008
Deculpe a demora, porém também achei estranho o meu último post ter sumido daqui, porém não importa, o que importa é que a última coisa que me lembro do meu último post é de ter te instruído a passar um TDataModule ao método por parâmetro. Contudo ao fazer mais um depuração do seu código vejo que isto não é necessário, vamos as considerações:
O Erro acontece aqui:
Agora veja o código que voce está instanciando no form filho de cadastro:
Repare que neste último código você instancia o dmCadFuncionarios, e faz referência a tabCadastro com outro DataModule (dmFuncionarios) que nem instanciado está, ou seja, o sistema está aquardando voce instanciar o DataModule dmFuncionarios, ou será que voce digitou errado :?:
Dê uma verificada.
Ednilson Campos
08/12/2008
procedure TfrmCadFuncionarios.FormCreate(Sender: TObject); begin inherited; dmCadFuncionarios := TdmCadFuncionarios.Create(Self); dmCadFuncionarios.cdsCadastro.Open; tabCadastro := dmCadFuncionarios.cdsCadastro; Generator := ´GEN_FUNCIONARIOS_ID´; end;
Eu acredito q talvez tenha msm q passar o DM como parametro tbm,eu bem tentei mas nao consegui.Se vc poder postar novamente por favor!
Desde já Agradeço!!
Ednilson Campos
08/12/2008
Fiz algumas alteraçoes e queria a opiniao de vcs! Pra resolve a questao q ja se prolonga eu apenas instanciei o DM de Cadastro juntamente com o de Consulta assim:
procedure TfrmConsFuncionarios.FormCreate(Sender: TObject); begin inherited; dmConsFuncionarios := TdmConsFuncionarios.Create(Self); dmConsFuncionarios.cdsFuncionarios.Open; dmCadFuncionarios := TdmCadFuncionarios.Create(Self); dmCadFuncionarios.cdsCadastro.Open; tabCadastro := dmCadFuncionarios.cdsCadastro; Generator := ´GEN_FUNCIONARIOS_ID´; tabConsulta := dmConsFuncionarios.cdsFuncionarios; sqlConsulta := dmConsFuncionarios.qryFuncionarios; NomeTabela := ´FUNCIONARIOS´; NomeCampo := ´NOME´; NomeTabelas.Caption := ´FUNCIONARIOS´; NomeCampos.Caption := ´NOME´; end;
Ai é só chamar no enveto dos botoes Editar ou Inserir:
procedure TfrmConsFuncionarios.btnEditarClick(Sender: TObject); begin Editar(TfrmCadFuncionarios,tabConsulta.fieldByName(´ID´).AsInteger); inherited; end; procedure TfrmConsFuncionarios.btnNovoClick(Sender: TObject); begin inherited; NovoRegistro(TfrmCadFuncionarios); //Registros(TfrmCadFuncionarios,INSERIR,tabConsulta.fieldByName(´ID´).AsInteger,tabCadastro); end;
O codigo do Metodo Editar:
procedure TfrmPai.Editar(ClasseForm: TFormClass;pID: Integer); var form : TForm; begin application.CreateForm(ClasseForm,form); tabCadastro.Close; tabCadastro.FetchParams; tabCadastro.Params.ParamByName(´pID´).AsInteger := pID; tabCadastro.Open; form.ShowModal; end;
O metodo Inserir é semelhante a este acima. Tive problemas pra liberar da memoria por isso vou postar tbm o OnClose:
procedure TfrmConsFuncionarios.FormClose(Sender: TObject; var Action: TCloseAction); begin inherited; dmConsFuncionarios.cdsFuncionarios.Close; FreeAndNil(dmConsFuncionarios); dmCadFuncionarios.cdsCadastro.Close; FreeAndNil(dmCadFuncionarios); FreeAndNil(frmConsFuncionarios); end;
A duvida é...existe algum problema em instanciar dois DataModules num mesmo Formulario como fiz acima? Ficaria melhor se pudesse deixar cada Formulario instanciando e liberando da memoria seus respectivos DataModules?
Micheus
08/12/2008
procedure TfrmPai.Editar(ClasseForm: TFormClass; pID: Integer); var form : TForm; begin application.CreateForm(ClasseForm,form); tabCadastro.Close; tabCadastro.FetchParams; tabCadastro.Params.ParamByName(´pID´).AsInteger := pID; tabCadastro.Open; form.ShowModal; end;
procedure TfrmConsFuncionarios.btnEditarClick(Sender: TObject); begin Editar(TfrmCadFuncionarios, tabConsulta.fieldByName(´ID´).AsInteger); inherited; end;
[b:7a4db5d2bd]Kenshin[/b:7a4db5d2bd], voce não postou como ficou o código no [i:7a4db5d2bd]OnClose[/i:7a4db5d2bd] do form [i:7a4db5d2bd]TfrmCadFuncionarios[/i:7a4db5d2bd], mas se ele ainda está como citado em post anterior (código abaixo) ele não está correto, a menos que vc tenha deixado apenas a linha [i:7a4db5d2bd]Action := caFree[/i:7a4db5d2bd]. Isto porque, baseado no processo de criação do form (código acima), a variável [i:7a4db5d2bd]frmCadFuncionarios[/i:7a4db5d2bd] não é utilizada e não corresponde à memória alocada para este form, visto que vc usa (acertadamente) uma instância local ao procedimento que o cria, lá no método [i:7a4db5d2bd]Editar[/i:7a4db5d2bd]:
procedure TfrmCadFuncionarios.FormClose(Sender: TObject; var Action: TCloseAction); begin inherited; Action := Cafree; frmCadFuncionarios := nil; end;
Outra coisa, se o [i:7a4db5d2bd]dmCadFuncionarios[/i:7a4db5d2bd] é usado apenas no [i:7a4db5d2bd]frmCadFuncionarios[/i:7a4db5d2bd], o mais apropriado é que este form crie e libere o referido datamodule.
Vale lembrar o que o colega [b:7a4db5d2bd]Discorpio[/b:7a4db5d2bd] citou neste [url=http://forum.devmedia.com.br/viewtopic.php?p=323848#323848]post[/url]: [color=darkblue:7a4db5d2bd][i:7a4db5d2bd]´o Delphi define por padrão todos os métodos de uma classe como estáticos´[/i:7a4db5d2bd][/color:7a4db5d2bd]
Caso vc não estivesse utilizando as variáveis dos datamodules criadas pelo Delphi, seus forms de cadastro não funcionariam.
Apesar de vc instanciar localmente o form de cadastro (não usar a variável global, criada pelo Delphi), os componentes data-aware do form de cadastro continuam apontando para os datasources contidos naquelas datamodules.
Abraços
Ednilson Campos
08/12/2008
Quando eu instancio o [b:0c0fa69fed]Data Module de Cadastro no Formulario de Cadastro[/b:0c0fa69fed] da erro na [b:0c0fa69fed]Tabela[/b:0c0fa69fed] q passo como parametro. Ao instanciar o [b:0c0fa69fed]Data Module de Cadastro no Formulario de Consulta[/b:0c0fa69fed] nao da erro. Eu nao consegui mas queria muito deixar cada Formulario cuidar de seu proprio Data Module.Da forma q eu fiz todo [b:0c0fa69fed]Formulario de Consulta[/b:0c0fa69fed] vai isntanciar dois Data Modules(Consulta e Cadastro) queria mudar isso. O metodo q instancia qualquer Formulario de Consulta fica no form Pai:
Procedure TfrmPai.CriaForm(ClasseForm: TFormClass); var form : TForm; Begin application.CreateForm(ClasseForm,form); form.ShowModal; end;
Para Cadastro tbm é no form Pai:
procedure TfrmPai.NovoRegistro(ClasseForm: TFormClass); var form : TForm; begin application.CreateForm(ClasseForm,form); tabCadastro.Cancel; tabCadastro.Append; tabCadastro.FieldByName(´ID´).AsInteger := GenProximoID(Generator); form.ShowModal; end;
O OnClose de Cadastro:
procedure TfrmCadFuncionarios.FormClose(Sender: TObject; var Action: TCloseAction); begin inherited; //ta comentado pq esta sendo instanciado no Form Consulta //dmCadFuncionarios.cdsCadastro.Close; //FreeAndNil(dmCadFuncionarios); FreeAndNil(frmCadFuncionarios);//neste caso libero apenas o Formulario end;
Para cada formulario de Consulta tenho um DM,para cada Form de Cadastro tenho outro DM.
Para cada Tabela no Data Module utlizo :
[b:0c0fa69fed]Um ClientDataset,um DatasetProvider, um SQLQruery e um DataSource [/b:0c0fa69fed]
Espero ter clariado mais meu problema q foi resolvido,mas como o Micheus disse
Nao entendo pq da erro quando instancio o [b:0c0fa69fed] Data Module no Form Cadastro[/b:0c0fa69fed] e nao da erro quando instancio no [b:0c0fa69fed] Form Consulta????[/b:0c0fa69fed]
Abraço!!
Ednilson Campos
08/12/2008
Ednilson Campos
08/12/2008
Nossa tantas alteraçoes foram feitas...e pra resolver apenas declarei as variaveis q preciso acima do implementation:
var frmPai: TfrmPai; tabCadastro,tabConsulta : Tclientdataset; sqlConsulta : TSQLQuery; Generator : String; pIDCadastro : Integer; pRegistro : Boolean; implementation
E mais agora posso usar apenas um metodo para Editar ou Inserir:
procedure TfrmPai.Registros(ClasseForm: TFormClass;pNovo: Boolean;pID: Integer); var form : TForm; Begin Try application.CreateForm(ClasseForm,form); if pNovo then begin tabCadastro.Cancel; tabCadastro.Append; tabCadastro.FieldByName(´ID´).AsInteger := GenProximoID(Generator); form.ShowModal; end else begin tabCadastro.Close; tabCadastro.FetchParams; tabCadastro.Params.ParamByName(´pID´).AsInteger := pIDCadastro; tabCadastro.Open; form.ShowModal; end; Except // End; end;
Discorpio,Micheus e os outros valew,valew msm!! Vo faze festa depois dessa...
Muito Obrigado!
Micheus
08/12/2008
procedure TfrmPai.NovoRegistro(ClasseForm: TFormClass); var form : TForm; begin application.CreateForm(ClasseForm,form); tabCadastro.Cancel; tabCadastro.Append; tabCadastro.FieldByName(´ID´).AsInteger := GenProximoID(Generator); form.ShowModal; end;
procedure TfrmCadFuncionarios.FormClose(Sender: TObject; var Action: TCloseAction); begin inherited; //ta comentado pq esta sendo instanciado no Form Consulta //dmCadFuncionarios.cdsCadastro.Close; //FreeAndNil(dmCadFuncionarios); FreeAndNil(frmCadFuncionarios);//neste caso libero apenas o Formulario end;
var frmPai: TfrmPai; tabCadastro,tabConsulta : Tclientdataset; sqlConsulta : TSQLQuery; Generator : String; pIDCadastro : Integer; pRegistro : Boolean; implementation
Abraços
Ednilson Campos
08/12/2008
Bom como vc disse esta acontecendo um erro,mas,é de vez enquando.Em tempo de programaçao,ao abrir um formulario qualquer durante o desenvolvimento da um erro de violaçao de memoria e em tempo de execuçao ainda nao deu erro. E msm eu instanciando o formulario de consulta com um metodo diferente do formulario de cadastro eu terei problemas? Nenhum formulario de Consuta deu erro ate o momento apenas os de Cadastro. Voltei as declaraçoes anteriores para Public
private
{ Private declarations }
public
tabCadastro,tabConsulta : Tclientdataset;
sqlConsulta : TSQLQuery;
Generator : String;
var
frmPai: TfrmPai;
//tabCadastro,tabConsulta : Tclientdataset;
implementationPara instanciar os formularios de consulta estou utilizando o metodo abaixo:
Procedure TfrmPai.CriaForm(ClasseForm: TFormClass); var form : TForm; Begin //Cria os formularios de consulta application.CreateForm(ClasseForm,form); form.ShowModal; FreeAndNil(form);//estou na duvida onde fica melhor liberar o form aki ou no OnClose? end; procedure TfrmClientes.FormClose(Sender: TObject; var Action: TCloseAction); begin inherited; dmClientes.cdsCadastro.Close; dmClientes.cdsCidades.Close; FreeAndNil(dmClientes); Action := CaFree;//esta é a forma correta? end;
Para os formularios de cadastro como postei anteriormente tenho este metodo:
procedure TfrmPai.Registros(ClasseForm: TFormClass;pNovo: Boolean;pID: Integer); var form : TForm; Begin Try application.CreateForm(ClasseForm,form); if pNovo then begin tabCadastro.Cancel; tabCadastro.Append; tabCadastro.FieldByName(´ID´).AsInteger := GenProximoID(Generator); form.ShowModal; end else begin tabCadastro.Close; tabCadastro.FetchParams; tabCadastro.Params.ParamByName(´pID´).AsInteger := pID; tabCadastro.Open; form.ShowModal; end; Except // End; end;
Voces nao poderiam passar um hexemplo de herança utilizando componentes DBExpress?[/u]