Selecao DevMedia QUERO SER PRIME

Fórum Objeto já destruido #373401

11/08/2009

0

Olá a todos.
Uso Delphi 7 + Firebird + Dbexpress
Erro de access violation muito curioso.
Tenho um Form Padrao usado em todos os cadastros, neste form inicializo um objeto:

[color=red:953f00c80d]procedure TFrCadastroPadrao.FormCreate(Sender: TObject);
begin
objpesquisa := TobjPesquisa.Create;
end;[/color:953f00c80d]

Tenho um outro Form descendente de TForm que uso para fazer um Mestre Detalhe, neste form faço referencia ao FormPadrao e monto dentro deste form num PageControl duas abas com dois formularios herdados do Form padrão uma aba é mestre e outra detalhe, abaixo parte do codigo.

unit uFrCadOrcDetOrc; // cadastrode orçamentos e detalhe orçamentos
interface
uses
Windows, Messages, SysUtils, Variants,Graphics, Controls,
Dialogs, ComCtrls,Db,uFrCadastroPadrao,Forms,Classes, ImgList,DbClient, ActnList, DBCtrls;

{Tecnica Conhecida como Hack acessar dados protegidos desta classe}
[color=red:953f00c80d]type
Tipo = class (TFrCadastroPadrao);[/color:953f00c80d]
type
[color=red:953f00c80d] TFrCadOrcDetOrc = class(TForm)
PageControl1: TPageControl;[/color:953f00c80d]

Código sair do form padrao:
procedure TFrCadastroPadrao.BtnSairClick(Sender: TObject);
begin
Close;
end;

Código destroy do form padrao:
procedure TFrCadastroPadrao.FormDestroy(Sender: TObject);
begin
if Assigned(objpesquisa) then // dá erro
objpesquisa.Free;
end;

Quando mando fechar o formulario, como são dois dentro de um ele passa pelo destroy duas vezes, quando fecha o primeiro e depois´passa novamente pelo destroy para fechar o segundo form e apresenta erro acess violation.

alguém pode me ajudar nisso.
Abraços e obrigado
Neto


Acneto

Acneto

Responder

Posts

11/08/2009

Dbergkamps10

Olá,
Veja qual o erro no access violation e crie uma exceção, tipo assim:
try
  //codigo onde ocorre o erro
except
on NomedoErro do
end;


Att
Dalton


Responder

Gostei + 0

12/08/2009

Osocram

tente fazer essa verificação no OnCloseQuery do form


Responder

Gostei + 0

12/08/2009

Emerson Nascimento

como objpesquisa está declarado no form padrão ?


Responder

Gostei + 0

12/08/2009

Acneto

[color=red:d9fd7686c9]No form padrao está como abaixo no create e no destroy[/color:d9fd7686c9]
procedure TFrCadastroPadrao.FormCreate(Sender: TObject);
begin
objpesquisa := TobjPesquisa.Create;
end;

procedure TFrCadastroPadrao.FormDestroy(Sender: TObject);
begin
objpesquisa.Free;
end;

[color=red:d9fd7686c9]E a unidade da classe pesquisa abaixo:[/color:d9fd7686c9]
unit uPesquisa;

interface

uses
SysUtils, DBClient;

[color=red:d9fd7686c9]Type
TObjPesquisa = class[/color:d9fd7686c9]
ftablename : string;
fCodigo : String;
fcdstabela : TClientDataSet;
ftituloPesquisa : string;
falturaGrid : integer;


fNomeCampos : Array[0..9] of string;
fDescCampos : Array[0..9] of string;
fSqlSelect : string;
fSqlWhere : Array[0..9] of string;
fSqlJoin : string;
fWidthCampos : Array[0..9] of integer;
fMaxLength : Array[0..9] of integer;
end;

var
objPesquisa : Tobjpesquisa;

implementation

{ TObjPesquisa }
.........
....
. etc..


Responder

Gostei + 0

12/08/2009

Emerson Nascimento

creio que o problema seja por conta de onde está declarada [i:2fde0c1fda]objPesquisa[/i:2fde0c1fda].

pelo que você mostrou

var
objPesquisa : Tobjpesquisa;

ela está declarada como uma variável global e pelo jeito você a quer local.

tire essa declaracão da unit [i:2fde0c1fda]uPesquisa[/i:2fde0c1fda] e coloque-a na seção private do form padrão e veja se atende ao que você precisa.


Responder

Gostei + 0

12/08/2009

Acneto

Olá emerson.en, obrigado pela ajuda, fiz como recomendado mas não deu certo, abaixo vou mostrar como está a estrutura

[color=red:b58f14f3a5]Formulario padrao[/color:b58f14f3a5]
unit uFrCadastroPadrao;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ExtCtrls, StdCtrls, Buttons, ActnList,
DBCtrls, Grids, ValEdit, DBXpress, DB, QStdCtrls, Mask,
DBClient, ImgList, uFrPrincipal, [color=red:b58f14f3a5]uPesquisa[/color:b58f14f3a5];

type
TFrCadastroPadrao = class(TForm)
procedure FormActivate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
[color=red:b58f14f3a5] objPesquisa : Tobjpesquisa;[/color:b58f14f3a5] >>conforme orientação
// --- ClientDataSet padrão dos cadastros
FCds : TClientDataSet;
protected

public
{ Public declarations }
end;
var
FrCadastroPadrao: TFrCadastroPadrao;

implementation
............
.......
...


[color=red:b58f14f3a5]Unidade Pesquisa[/color:b58f14f3a5]
unit uPesquisa;

interface

uses
SysUtils, DBClient;

Type
TObjPesquisa = class
ftablename : string;
fCodigo : String;
fcdstabela : TClientDataSet;
ftituloPesquisa : string;
falturaGrid : integer;

fNomeCampos : Array[0..9] of string;
fDescCampos : Array[0..9] of string;
fSqlSelect : string;
fSqlWhere : Array[0..9] of string;
fSqlJoin : string;
fWidthCampos : Array[0..9] of integer;
fMaxLength : Array[0..9] of integer;
end;

implementation

{ TObjPesquisa }

end.

[color=red:b58f14f3a5]Unidade ParametrizaObjeto[/color:b58f14f3a5]

estes parametros são chamados do botão pesquisa de cada formulario de cadastro que é herdado do formulario padrao
procedure TFrCadClientes.BtnPesquisarClick(Sender: TObject);
begin
inherited;
[color=red:b58f14f3a5] ParametrizaObjClientes;[/color:b58f14f3a5]
[color=red:b58f14f3a5] UnFuncoesCliente.InstanciarForm(´FrPesquisa´);[/color:b58f14f3a5] >> chama form pesquisa
UnFuncoesCliente.ApresentarDados(self,List,objpesquisa.fcdstabela);
end;

Nesta unidade atribuo valores aos ponteiros (variaveis) criadas na unidade Pesquisa

[color=red:b58f14f3a5]unit UnParametrizaObj;[/color:b58f14f3a5]
interface

uses
SysUtils, DBClient, uPesquisa;

procedure ParametrizaObjClientes;

implementation

uses undmcliente;

procedure ParametrizaObjClientes;
begin
objPesquisa.ftablename := ´CLIENTES´;

objPesquisa.fCodigo := ´0´;
objPesquisa.fcdstabela := DmCliente.CdsClientes;
objPesquisa.ftituloPesquisa := ´Consulta de Clientes´;
objPesquisa.falturaGrid := 400;

objPesquisa.fSqlSelect := ´Select * From ´ + objPesquisa.ftablename;
objPesquisa.fSqlJoin := ´ ´;

objPesquisa.fNomeCampos[0] := ´Cli_RazaoSocial´;
objPesquisa.fNomeCampos[1] := ´Cli_Fantasia´;
objPesquisa.fNomeCampos[2] := ´Cli_Telefone´;
objPesquisa.fNomeCampos[3] := ´Cli_Celular´;
objPesquisa.fNomeCampos[4] := ´Cli_Telefax´;
objPesquisa.fNomeCampos[5] := ´Cli_Cod´;

objPesquisa.fDescCampos[0] := ´Razão Social da Empresa´;
objPesquisa.fDescCampos[1] := ´Nome Fantasia´;
objPesquisa.fDescCampos[2] := ´Telefone-PABX´;
objPesquisa.fDescCampos[3] := ´Celular´;
objPesquisa.fDescCampos[4] := ´Telefax´;
objPesquisa.fDescCampos[5] := ´Código´;

objPesquisa.fWidthCampos[0] := 400;
objPesquisa.fWidthCampos[1] := 200;
objPesquisa.fWidthCampos[2] := 120;
objPesquisa.fWidthCampos[3] := 120;
objPesquisa.fWidthCampos[4] := 120;
objPesquisa.fWidthCampos[5] := 60;

objPesquisa.fMaxLength[0] := 20;
objPesquisa.fMaxLength[1] := 20;
objPesquisa.fMaxLength[2] := 12;
objPesquisa.fMaxLength[3] := 12;
objPesquisa.fMaxLength[4] := 12;
objPesquisa.fMaxLength[5] := 4;

objPesquisa.fSqlWhere[0] := ´Where Cli_RazaoSocial ´;
objPesquisa.fSqlWhere[1] := ´Where Cli_Fantasia ´;
objPesquisa.fSqlWhere[2] := ´Where Cli_Telefone ´;
objPesquisa.fSqlWhere[3] := ´Where Cli_Celular ´;
objPesquisa.fSqlWhere[4] := ´Where Cli_Telefax ´;
objPesquisa.fSqlWhere[5] := ´Where Cli_Cod ´;

end;

end.

[color=red:b58f14f3a5]Formulario Pesquisa descendente de TFom[/color:b58f14f3a5]

unit uFrPesquisa;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, Grids, DBGrids, DbClient, ComCtrls, uPesquisa,
ActnList;

const
ColorPadrao = clSilver;
ColorColumn = clAqua;
pParametroVazio = ´ ´;
ColorItems = clred;

type
TipoParametro = (ftVazio , ftString , ftDataNull);

TFrPesquisa = class(TForm)

procedure FormShow(Sender: TObject);
procedure FormCreate(Sender: TObject);

private
{ Private declarations }

objPesquisa : Tobjpesquisa;

Coluna : TColumn;
idxdescricao : integer;

fDadosEmCache : boolean;

procedure PreencheGridListBox;
procedure AlterarCaption;
public
{ Public declarations }

protected
ftabela : string;
fcampo : string;
fparametro : string;
finstrucaosql : string;

end;

var
FrPesquisa: TFrPesquisa;

implementation

uses UnFactoryMethod, UnDmCliente, UnDmServidor;

{$R *.dfm}

procedure TFrPesquisa.FormCreate(Sender: TObject);
begin
FrPesquisa.Caption := [color=red:b58f14f3a5]objPesquisa.ftituloPesquisa;[/color:b58f14f3a5]
lbcampos.ItemIndex := 0;
end;

procedure TFrPesquisa.FormShow(Sender: TObject);
begin
PreencheGridListBox;

lbdescricao.ItemIndex := 0;
idxdescricao := lbdescricao.ItemIndex;
edtpesquisa.MaxLength := [color=red:b58f14f3a5]objpesquisa.fMaxLength[idxdescricao];[/color:b58f14f3a5]
lbdescricao.SetFocus;

DsPesquisa.dataset := [color=red:b58f14f3a5]objpesquisa.fcdstabela;[/color:b58f14f3a5] dbgPesquisa.DataSource := dspesquisa;
DbgPesquisa.Height := [color=red:b58f14f3a5]objPesquisa.falturaGrid;[/color:b58f14f3a5]
objpesquisa.fcdstabela.IndexFieldNames := [color=red:b58f14f3a5]objPesquisa.fNomeCampos[ idxdescricao ];[/color:b58f14f3a5]
AlterarCaption();
Stb.Panels.Items[0].Text := ´Tabela: ´ + [color=red:b58f14f3a5]objPesquisa.ftablename;[/color:b58f14f3a5]
end;

procedure TFrPesquisa.PreencheGridListBox;
var
i : integer;
s : string;
begin

for i := 0 to Length(objPesquisa.fDescCampos)-1 do
begin
s := objPesquisa.fDescCampos[i];
if trim(objPesquisa.fDescCampos[i]) <> ´´ then
begin
LbDescricao.Items.Add( objPesquisa.fDescCampos[i] );
LbCampos.Items.Add( objPesquisa.fNomeCampos[i]);

Coluna := DbgPesquisa.Columns.Add;
Coluna.Title.Caption := objPesquisa.fDescCampos[i];
Coluna.FieldName := objPesquisa.fNomeCampos[i];
Coluna.Width := objPesquisa.fWidthCampos[i];
end;
end;
end;

procedure TFrPesquisa.AlterarCaption;
const
Texto = ´Pesquisa Indexada pelo Campo ´;
begin

lblPesquisa.Caption := Texto + ´ ´ + objpesquisa.fDescCampos[ idxdescricao ];
end;
end.

Ufa!!!
obrigado a todos.
Neto


Responder

Gostei + 0

12/08/2009

Emerson Nascimento

acho que falei bobagem...

os procedimentos/funcoes externas precisam receber a instancia correta do objeto objPesquisa.

tente assim:

unit uFrCadastroPadrao;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ExtCtrls, StdCtrls, Buttons, ActnList,
  DBCtrls, Grids, ValEdit, DBXpress, DB, QStdCtrls, Mask,
  DBClient, ImgList, uFrPrincipal, uPesquisa;

  type
    TFrCadastroPadrao = class(TForm)
      procedure FormActivate(Sender: TObject);
      procedure FormShow(Sender: TObject);
      procedure FormClose(Sender: TObject; var Action: TCloseAction);
    private
      { Private declarations }
      // --- ClientDataSet padrão dos cadastros
      FCds : TClientDataSet;
    protected

    public
      { Public declarations }
      objPesquisa: Tobjpesquisa;
    end;

//var
//  FrCadastroPadrao: TFrCadastroPadrao;

implementation
............ 


procedure TFrCadClientes.BtnPesquisarClick(Sender: TObject);
begin
  inherited;
  ParametrizaObjClientes(objPesquisa);
  UnFuncoesCliente.InstanciarForm(´FrPesquisa´); >> chama form pesquisa
  UnFuncoesCliente.ApresentarDados(self,List,objpesquisa.fcdstabela);
end; 


procedure ParametrizaObjClientes(objPesq: Tobjpesquisa);
begin
  objPesq.ftablename := ´CLIENTES´;

  objPesq.fCodigo := ´0´;
  objPesq.fcdstabela := DmCliente.CdsClientes;
  objPesq.ftituloPesquisa := ´Consulta de Clientes´;
  objPesq.falturaGrid := 400;

  objPesq.fSqlSelect := ´Select * From ´ + objPesq.ftablename;
  objPesq.fSqlJoin := ´ ´;

  objPesq.fNomeCampos[0] := ´Cli_RazaoSocial´;
  objPesq.fNomeCampos[1] := ´Cli_Fantasia´;
  objPesq.fNomeCampos[2] := ´Cli_Telefone´;
  objPesq.fNomeCampos[3] := ´Cli_Celular´;
  objPesq.fNomeCampos[4] := ´Cli_Telefax´;
  objPesq.fNomeCampos[5] := ´Cli_Cod´;

  objPesq.fDescCampos[0] := ´Razão Social da Empresa´;
  objPesq.fDescCampos[1] := ´Nome Fantasia´;
  objPesq.fDescCampos[2] := ´Telefone-PABX´;
  objPesq.fDescCampos[3] := ´Celular´;
  objPesq.fDescCampos[4] := ´Telefax´;
  objPesq.fDescCampos[5] := ´Código´;

  objPesq.fWidthCampos[0] := 400;
  objPesq.fWidthCampos[1] := 200;
  objPesq.fWidthCampos[2] := 120;
  objPesq.fWidthCampos[3] := 120;
  objPesq.fWidthCampos[4] := 120;
  objPesq.fWidthCampos[5] := 60;

  objPesq.fMaxLength[0] := 20;
  objPesq.fMaxLength[1] := 20;
  objPesq.fMaxLength[2] := 12;
  objPesq.fMaxLength[3] := 12;
  objPesq.fMaxLength[4] := 12;
  objPesq.fMaxLength[5] := 4;

  objPesq.fSqlWhere[0] := ´Where Cli_RazaoSocial ´;
  objPesq.fSqlWhere[1] := ´Where Cli_Fantasia ´;
  objPesq.fSqlWhere[2] := ´Where Cli_Telefone ´;
  objPesq.fSqlWhere[3] := ´Where Cli_Celular ´;
  objPesq.fSqlWhere[4] := ´Where Cli_Telefax ´;
  objPesq.fSqlWhere[5] := ´Where Cli_Cod ´;
end;



Responder

Gostei + 0

13/08/2009

Acneto

Ótimo emerson acho que estamos quase lá.
ao pressionar btnPesquisar retorna access violation na linha abaixo:

procedure TFrPesquisa.FormCreate(Sender: TObject);
begin
[color=red:a1ab75f5fb] FrPesquisa.Caption := objPesquisa.ftituloPesquisa;[/color:a1ab75f5fb] >>> acess violation
lbcampos.ItemIndex := 0;
end;

Gostaria de saber porque não declarar a variavel FrCadastroPadrao : TFrCadastroPadrao no formulario padrao?
    public 
      { Public declarations } 
      objPesquisa: Tobjpesquisa; 
    end; 

//var 
//  FrCadastroPadrao: TFrCadastroPadrao; >>>>  AQUI ????

implementation 


Abraço
Neto


Responder

Gostei + 0

13/08/2009

Rodc

Na hora de destruir, ao invés de usar
objpesquisa.Free;
use
FreeAndNil(objpesquisa);



Responder

Gostei + 0

13/08/2009

Acneto

Ok Rodc farei isso
mas o problema ainda continua ao referenciar ao objeto no frPesquisa

Obrigado
Neto


Responder

Gostei + 0

13/08/2009

Emerson Nascimento

é preciso conhecer as seguintes rotinas:

UnFuncoesCliente.InstanciarForm
UnFuncoesCliente.ApresentarDados

quanto à pergunta sobre a declaração da variável FrCadastroPadrao... a maioria das vezes ela é declarada mas não é usada. como é uma variável global, ocupa espaço desnecessário na memória. se você a utilizar, mantenha a declaração.


Responder

Gostei + 0

13/08/2009

Acneto

Ótimo,
segue os codigos.

procedure InstanciarForm(Const Formulario:String);overload; //Para ter métodos sobrecarregados
begin
try
  FForm := FormFactory.CreateForm(Formulario);
  FForm.ShowModal;
  FreeAndNil(FForm);
except
 on  EAssertionFailed do
     showmessage(´Nome errado´);
end;
end;


procedure ApresentarDados(formulario: Tform;Vle:TValueListEditor;
  Cds: TClientDataSet);
var
  i,idx:integer;
  Ctrl:TObject;
  s : string;
  t : integer;
  r : Real;
begin
  try
    with cds do
      for i := 1 to vle.RowCount-1 do
        begin
          Ctrl := RetornarComponente(formulario,Vle.Cells[ 1 , i ]);
          if Ctrl Is TEdit Then
            case FieldByName(Vle.Cells[ 0 , i ]).DataType of
              ftFMTBcd:
                begin
                  t := cds.FieldByName(Vle.Cells[ 0 , i ]).Size;
                  r := cds.FieldByName(Vle.Cells[ 0 , i ]).asfloat;
                  TEdit(Ctrl).Text := FloatToStrf( r , ffNumber, 12, t);
                end;
            else
              TEdit(Ctrl).Text:= FieldByName(Vle.Cells[ 0 , i ]).AsString
            end
          else
            if Ctrl Is TMaskEdit Then
              TMaskEdit(Ctrl).Text:= FieldByName(Vle.Cells[ 0 , i ]).AsString
            else
              if Ctrl Is TComboBox Then
                begin
                s := FieldByName(Vle.Cells[ 0 , i ]).AsString;
                idx := TComboBox(Ctrl).Items.IndexOf( s );
                TComboBox(Ctrl).ItemIndex:=idx;
                end;
        end;
  except
    on e:exception do
      begin
        TErros.GetMensagem(E);
      end;
  end;
end;



Abraço e obrigado
Neto


Responder

Gostei + 0

14/08/2009

Emerson Nascimento

o form pesquisa deve ser criado de modo a receber o objeto de pesquisa correto. talvez não seja possível criar através desse procedimento [i:53f0ac0c1a]InstanciarForm[/i:53f0ac0c1a], a menos que você faça uma sobrecarga, passando como parâmetro o objeto de pesquisa correto.

eu faria uma [i:53f0ac0c1a]class function[/i:53f0ac0c1a] para o formulário de pesquisa e os demais deixaria serem criados pelo [i:53f0ac0c1a]InstanciarForm[/i:53f0ac0c1a].
assim a chamada poderia ficar no form padrão:
procedure TFrCadastroPadrao.BtnPesquisarClick(Sender: TObject);
begin
  // class function passando o objPesquisa como parâmetro.
  // essa class function cria o form e o exibe modal.
  // antes de apresentar os dados, avalio o retorno,
  // pois o usuário pode ter cancelado a pesquisa.
  if TFrPesquisa.Execute(objPesquisa) then
    UnFuncoesCliente.ApresentarDados(self,List,objpesquisa.fcdstabela);
end;

e, nos forms herdados, faria:
procedure TFrCadClientes.BtnPesquisarClick(Sender: TObject);
begin
  ParametrizaObjClientes(objPesquisa); // parametriza
  inherited; // cria o form com o objeto já parametrizado
end;

note que, se a linha [i:53f0ac0c1a]ParametrizaObjClientes(objPesquisa)[/i:53f0ac0c1a] estivesse no [i:53f0ac0c1a]OnCreate[/i:53f0ac0c1a] do form herdado, não haveria necessidade de implementar o evento [i:53f0ac0c1a]BtnPesquisarClick[/i:53f0ac0c1a] nesse form herdado, pois o form padrão já estaria com tudo resolvido.


Responder

Gostei + 0

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

Aceitar