Ayri formlari, ayni kodla acan kod ancak bazen hata veriyor?

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Glen
Üye
Mesajlar: 277
Kayıt: 12 Eki 2005 11:58

Ayri formlari, ayni kodla acan kod ancak bazen hata veriyor?

Mesaj gönderen Glen »

Merhaba arkadaşlar..

Bir procedure yazdim kodu kisaltmak icin, bazi sorunlar yaratiyor ve sormak istedigim bir takim sorular var yardimci olabilirseniz sevinirim.

Formlarim hep ayni kodlarla aciliyor degisen tek $ey ise isimler, o yuzden asagidaki procedure'u kullanarak formlari aciyorum.. Gorudgunuz uzere bahsi gecen 2 tane procedure'um var..

1. FormAc
2. FormAc'in icinde kullandigi AciksaKapat fonksiyonu..

AciksaKapat'i ekliyorum cunku ayni formun 2 kere acilmasini istemiyorum,
ve her acildiginda Anaformumdaki AcikFormlar isimli TList'ime formumu ekliyorum ki acik olan formlarimi gorebilmek icin..

Kod: Tümünü seç

anaform.AcikFormlar.Add(xForm);
Asagidaki FormAc procedure'u

Kod: Tümünü seç

procedure FormAc(xSenderForm: TForm; xSenderEdit: TcxButtonEdit; xKontrolEdit: TCxButtonEdit; xSQL : TStringList; xClassName : TFormClass;
          xFormStyle : TFormStyle; xVariables : TStringList; xValues : array of Variant);
var
  xQuery : TAdoQuery;
  xForm : TForm;
  i : integer;
begin
      AciksaKapat(xClassName.ClassName, True);

      xForm := xClassName.Create(xSenderForm);
      anaform.AcikFormlar.Add(xForm);

      xQuery := TADOQuery(xForm.FindComponent('ListeQuery'));
      xQuery.Close;
      xQuery.SQL.Clear;
      xQuery.SQL.Text := xSQL.Text;
      xQuery.Active := True;

      if (xSenderEdit <> nil) then
      begin
          SetObjectProp(xForm, '_xGonderenEdit', xSenderEdit);
      end;
      
      if (xKontrolEdit <> nil) then
      begin
          SetObjectProp(xForm, '_xKontrolEdit', xKontrolEdit);
      end;

      if (xVariables <> nil) then
      begin
          For i := 0 to xVariables.Count-1 do
          begin
              SetPropValue(xForm, xVariables[i], xValues[i]);
          end;
      end;

      if (xFormStyle = FsNormal) then
      begin
          xForm.FormStyle := FsNormal;
          xForm.WindowState := WsNormal;
          xForm.Position := PoScreenCenter;
          xForm.Visible := False;
          xForm.ShowModal;
          exit;
      end else
      if (xFormStyle = FsMdiChild) then
      begin
          xForm.FormStyle := FsMdiChild;
          xForm.Show;
          exit;
      end;
end;
Bu da AciksaKapat procedure'u

Kod: Tümünü seç

procedure AciksaKapat(xClassName : string);
var
  i : integer;
begin
    if anaform.AcikFormlar.Count = 0 then exit;

    for i := 0 to AcikFormlar.Count-1 do
    begin

      if TForm(AcikFormlar[i]).ClassName = xClassName then
      begin
            TForm(AcikFormlar[i]).Close;
        break;
      end;

    end;
end;

Ve bunu her kullanan formumun OnClose eventine, Asagidaki kodu ekliyorum.

Kod: Tümünü seç

  Anaform.AcikFormlar.Remove(self);
  Action := CaFree;
  Self := nil;
Kodun kullanimi ise $u $ekilde..

Kod: Tümünü seç

var
  xValues : array of Variant;
begin
    strSQL.Text := 'SELECT * FROM CH';
    Formlar.FormAc(Self, nil, nil, StrSQL, TChKart, FsMdiChild, nil, xValues);
end;
Ben herhangi bir mantik hatasi göremedim, yani formlar kapatilirken kendini remove ediyor, eger tekrar ayni sey acilmaya calisilirsa, acikform.Close seklinde kapatiliyor, ve dolayli yoldan tekrar remove ediliyor.

Ancak anlayamadigim, bu kod bazen access violation hatasi veriyor. Bazen ise vermiyor.. Sebepleri ne olabilir? Ayrica bu kod cok isime yariyor, ama sizce memory leak vs gibi sorunlar cikarir mi?

Sorum biraz uzun oldu, ama benim icin cok onemli birsey, umarim yardimci olursunuz..

Simdiden tesekkür ederim, herkese kolay gelsin, iyi calismalar.
Glen
Üye
Mesajlar: 277
Kayıt: 12 Eki 2005 11:58

Mesaj gönderen Glen »

Soru biraz uzun oldu sanirim ondan pek cevaplanamadi..

Bir fikri olan yok mu acaba?
Kullanıcı avatarı
bobasturk
Kıdemli Üye
Mesajlar: 1387
Kayıt: 20 May 2004 08:39
Konum: Düzce

Mesaj gönderen bobasturk »

merhaba,

bu konu bilgimi aşıyor. size faydalı ve temeli olan bir bilgi veremeyeceğim ama butona bastığınızda form açıksa

Kod: Tümünü seç

xform.bringtofront;
ile öne getirseniz. kapat aç olayını yapmasanız. normalde hafızadan silindiği için sorun olmaz gibi görünüyor ama belki arada bir hafızayı boşaltamıyor olabilir sistem.

kolay gelsin.
Şefkat-u Merhamette Güneş Gibi Ol.
Başkalarının Kusurunu Örtmekte Gece Gibi Ol.
Sehavet-u Cömertlikte Akarsu Gibi Ol.
Hiddet-u Asabiyette Ölü Gibi Ol.
Tevazu-u Mahviyette Toprak Gibi Ol.
Ya Olduğun Gibi Görün Ya Göründüğün Gibi Ol.

Resim
Glen
Üye
Mesajlar: 277
Kayıt: 12 Eki 2005 11:58

Mesaj gönderen Glen »

Öncelikle cevapaldiginiz icin tesekkür ederim.
BringToFront'un ise yarayacagini düsünmüyorum cünkü xForm scope icinde tanimlanmis bir degisken oldugu icin yani Global olmadigi icin o kod yine access violation hatasi verecektir. Baska bir cozum dusunmeliyiz sanirim :)
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3081
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Mesaj gönderen sabanakman »

Kodlarınızı çok iyi inceleyemedim ama basit bir öneri:

Kod: Tümünü seç

AciksaKapat(xClassName.ClassName, True);
xForm := xClassName.Create(xSenderForm); 
yerine kapatmadan öne getirmeyi deneyin.Bu 2 satırın yerine

Kod: Tümünü seç

xForm:=nil;
for i := 0 to AcikFormlar.Count-1 do 
if TForm(AcikFormlar[i]).ClassName = xClassName then begin
  //TForm(AcikFormlar[i]).Close; yerine
  xForm:=TForm(AcikFormlar[i]);
  break;
end;
if Assigned(xForm) then xForm.BringToFront else xForm := xClassName.Create(xSenderForm);
yazın. Belki sorun hallolabilir.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Glen
Üye
Mesajlar: 277
Kayıt: 12 Eki 2005 11:58

Mesaj gönderen Glen »

Ilginiz icin tesekkur ederim Saban bey,
Sanirim hatanin kaynaklandigi kisim asagidaki kisim yani sizin de süphelendiginiz kisim :)

Kod: Tümünü seç

if TForm(AcikFormlar[i]).ClassName = xClassName then begin 
  //TForm(AcikFormlar[i]).Close; yerine 
  xForm:=TForm(AcikFormlar[i]); 
  break; 
end; 
Eger form free olmussa ve AcikFormlar listesinden de remove edilmemisse,

If TForm(AcikFormlar) seklinde erisim yapildiginda pointerin point ettigi nesne olmadigindan dolayi access violation hatasi veriyor. O yuzden cok dikkatli bir sekilde yapmak gerekiyor.

Bu baska bir konuyu aciyor, pointerin point ettigi nesne hala varmi yok mu kontrolu. Bu konuyu arastirdim ancak maalesef delphide boyle bir sey yok.

Kod: Tümünü seç

var
x, a : TForm;
begin
a := TForm.Create(self);
x := a;
a.Free;
If assigned(x) then.... 
Dedigimizde Assigned degeri True geliyor cunku pointer vaziyetindeki X nesnesi hala var, ancak icerdigi deger olan A nesnesi yok. O yuzden erismeye calisinca access violation hatasi veriyor.

Tekrardan tesekkur ederim ilginiz icin,

Iyi calismalar, kolay gelsin.
Kullanıcı avatarı
sadettinpolat
Moderator
Mesajlar: 2131
Kayıt: 07 Ara 2003 02:51
Konum: Ankara
İletişim:

Mesaj gönderen sadettinpolat »

Kod: Tümünü seç

var
x, a : TForm;
begin
a := TForm.Create(self);
x := a;
a.Free;
a:=nil;
If assigned(x) then.... 

seklinde deneyin
"Sevmek, ne zaman vazgececegini bilmektir." dedi, bana.

---
http://sadettinpolat.blogspot.com/
Glen
Üye
Mesajlar: 277
Kayıt: 12 Eki 2005 11:58

Mesaj gönderen Glen »

sadettinpolat yazdı:

Kod: Tümünü seç

var
x, a : TForm;
begin
a := TForm.Create(self);
x := a;
a.Free;
a:=nil;
If assigned(x) then.... 

seklinde deneyin
Assigned degeri kodda yine TRUE geliyor cunku X nesnesi hala duruyor sadece point ettigi nesne (a nesnesi) free edilmis.

Yani yine point edilen nesnenin var olup olmadigi belli olmuyor.. Arastirdim bunu yani dedigim gibi ancak merak ettigim bu delphinin (kullandigim version 7) bir eksigimi acaba diger dillerde de bu eksik varmi
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3081
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Mesaj gönderen sabanakman »

Burada programcıya ait bir kontrolsüzlük söz konusu. İpleri her zaman programcı elinde tutmalı. Yukarıdaki önerimi 2 şekilde değiştirmek istiyorum. 1-try-except içinde tutarak anlamak

Kod: Tümünü seç

xForm:=nil;
try
  for i := 0 to AcikFormlar.Count-1 do
  if TForm(AcikFormlar[i]).ClassName = xClassName then begin
    //TForm(AcikFormlar[i]).Close; yerine
    xForm:=TForm(AcikFormlar[i]);
    break;
  end;
except
  xForm:=nil;
end;
if Assigned(xForm) then xForm.BringToFront else xForm := xClassName.Create(xSenderForm);
Burada F9 la çalışan programda; silinen bir forma rast geldiğinde delphi kızıp hata mesajı verse de windows ortamında çift tıklayarak çalışan .exe programdan hata mesajı almayacaksın. (Bknz. Options->Debugger Exceptions)

2-AcikFormlar isimli bir listeyle hiç muhatap olmadan TComponent içindeki listeden faydalanmak. (Gönlümden geçen metot budur)

Kod: Tümünü seç

xForm:=nil;
for i := 0 to xSenderForm.ComponentCount-1 do
if TForm(xSenderForm.Components[i]).ClassName = xClassName then begin
  //TForm(AcikFormlar[i]).Close; yerine
  xForm:=TForm(xSenderForm.Components[i]);
  break;
end;
if Assigned(xForm) then xForm.BringToFront else xForm := xClassName.Create(xSenderForm); 
gibi. Burada bileşenler zaten kendi içlerinde oluşturulmuş nesnelerin bir listesini tuttuğundan ayrı bir liste ile takip etmek zorunda kalmadık. Ayrıca free edilen bir form bu listeden otomatikman VCL tarafından çıkacak şekilde yazılmıştır. İyi çalışmalar.
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Değişken, nesnenin kendisini tutmaz. Pointer'ını saklar. Nesneyi Free yaptığınızda daha sonraki işlemlerde hata yapmamak için değişkeni de nil yaparsınız.

Bu sayede nesneyi Free yapıp yapmadığınızı değişkenin nil olup olmadığına bakarak karar verirsiniz.
Glen
Üye
Mesajlar: 277
Kayıt: 12 Eki 2005 11:58

Mesaj gönderen Glen »

Verdiginiz bilgiler icin tesekkur ederim, hepsini dikkate alip kodlari duzenleyecegim yine de dediginiz gibi herseyi cok dikkatli ve kontrollü yapmak gerekiyor.

Iyi calismalar, kolay gelsin.
Cevapla