Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
MdiChield formu aynı projede show ve showmodal ile çağırma
#1
Arkadaşlar merhaba,

soruyu daha anlaşılabilir sormak için ufak bir sample hazırlayıp ekledim,

-> Projeyi çalıştırın
-> Formlar menüsünden Form 2 yi tıklayın, form üzerindeki kontrol butonunu tıklayın, Assigned mesajını göreceksiniz.
-> Form 2 açık dururken Formlar menüsünden Form 3 ü tıklayın ve açılan form üzerindeki "Form2 yi Showmodal olarak Çağır (Unit2)" butonunu tıklayın
-> Form 2 bu defa Showmodal formda açılacak. Yine kontrol e tıklandığında Assigned mesajı görüntülenir,
-> Sırayla son açılan formdan itibaren Kapatın sadece Form 2 mdichild form kalsın,
-> kontrol tıklandığında form not assigned a düşecek,

yapmaya çalıştığım ise form 2 showmodal olarak çağırılp kapatıldıktan sonra mdichild halinin not assigned a düşmemesi, umarım net anlatabilmişimdir.

Saygılar.


Ek Dosyalar
.zip   mdichieldshowmodal.zip (Dosya Boyutu: 2,5 MB / İndirme Sayısı: 4)
Cevapla
#2
Merhaba,

  1. Form nesnelerini global değişken olarak tanımlamışsınız
  2. Form2'yi kapatırkan NIL'e çekiyorsunuz. Yani nesnenin referansını boşaltıyorsunuz. TForm2 nesnesini birden fazla kez oluşturup Form2 adlı değişkene birden fazla kez refere ediyorsunuz. Sorun bundan kaynaklanıyor.
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#3
(07-12-2024, Saat: 09:37)uparlayan Adlı Kullanıcıdan Alıntı: Merhaba,

  1. Form nesnelerini global değişken olarak tanımlamışsınız
  2. Form2'yi kapatırkan NIL'e çekiyorsunuz. Yani nesnenin referansını boşaltıyorsunuz. TForm2 nesnesini birden fazla kez oluşturup Form2 adlı değişkene birden fazla kez refere ediyorsunuz. Sorun bundan kaynaklanıyor.
1.Public yada private olması hiçbir şey değiştirmedi,
2.Form child form da çağrılmışsa modeselect değişkeni false değerinde oluyor formclose da bu değişkene bakarak showmodal durumunda iken kapatma oluyorsa NIL'e çekmiyor sadece childform çıkışında çekiyor.

Tam da dediğiniz gibi aslında, Form2 yi birden fazla kez birbirlerinden bağımsız şekilde oluşturmak istiyorum ama bilgim yetmedi, birisi child form da diğeri showmodal da, form üzerinde tablolar da mevcut, bağımsız oluşturamadığım için esas sorunu çıkartan onlar.
Cevapla
#4
Private veya public olması ile ilgili bir şey söylemedim ama ifadem yanıltıcı olmuş olabilir, 

Formları yönetmek çok geniş bir kavram olduğu için sadece sorunuz çerçevesindeki kısım ile sınırlı tutuyorum o nedenle detayları kodlar üzerinden açıklayayım.

Ön hazırlık olması ve kapanırken bellek sızıntısı oluşuyor mu oluşmuyor mu basitçe anlamak için .DPR dosyasındaki begin bloğuna aşağıdaki kodu ekliyoruz.

...
begin
  ReportMemoryLeaksOnShutdown := True;       // bellek sızıntıları varsa program kapanırken bir rapor göstersin.
  Application.Initialize;
...

Owner mekanizması denilen bir kavram var. Buna göre bir nesneyi oluştururken onun varlığını ve yokluğunu kontrol edecek bir sahip belirtmek gerekir. Dolayısıyla ana nesne yok edilirken ona bağlı alt nesneler de bu sayede otomatik olarak yok edilebilir.

unit Unit1;

interface
...
...

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses unit2, unit3;

procedure TForm1.Form21Click(Sender: TObject);
begin
  { artık global bir değişken (Form3) kullanmadığımız için bu kısım geçerli değil.
  Application.CreateForm(TForm3, Form3);
  Form3.ShowModal;
  Form3.Free;
  }


  with TForm3.Create(Self) do  // SELF = Bu nesne, yani bu durumda Form1 nesnesidir.
  try
    ShowModal;
  finally
    Free;
  end;

end;

{ bu sizin orjinal kodunuz;
procedure TForm1.Formlar2Click(Sender: TObject);
begin
  if Assigned(Form2) then
    Form2.show
  else
    begin
      Application.CreateForm(TForm2, Form2);
      Form2.FormStyle := fsMDIChild;
      Form2.Show;

    end;
end;
}

procedure TForm1.Formlar2Click(Sender: TObject);
var
  I: Integer;
  Form2Exists: Boolean;
begin
  Form2Exists := False;

  // Tüm MDIChild formları kontrol et
  for I := 0 to MDIChildCount - 1 do
  begin
    if MDIChildren[I] is TForm2 then
    begin
      Form2Exists := True;
      MDIChildren[I].Show; // Zaten varsa, göster
      exit;
    end;
  end;


  if not Form2Exists then
  begin
   with TForm2.Create(Self) do
   try
     FormStyle := fsMDIChild;
     Show;
   finally
     //Free; // doğrudan free etmiyoruz çünkü bu işi kullanıcı formun kapatma butonuna basarak kendisi manuel olarak gerçekleştirecek. detaylar TForm2.FormClose'da
   end;
  end;
end;

end.

2. forma gelelim;

unit Unit2;

interface
...
...


// Bu kısmı iptal edin.
//var
//  Form2: TForm2; // bu tanıma gerek yok

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
  { bu kısım anlamını yitirdi. 
  if Assigned(Form2) then
    ShowMessage('Assigned')
  else
    ShowMessage('not Assigned');
  }
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  Close;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := TCloseAction.caFree; // bu atamayı yaparak aslında FREE işlemini bu kısım VCL'in derinliklerinde gerçekleştiriyor zaten.
  //Form2 := Nil; // global bir değişkenimiz yok, o nedenle olmayan bir değişkenin referansını da artık sıfırlamamıza gerek yok.
end;

end.

3. forma gelelim;

unit Unit3;

interface
...
...

// bu kısmı iptal edin
//var
//  Form3: TForm3;

implementation

{$R *.dfm}

uses unit2;

procedure TForm3.Button1Click(Sender: TObject);
//var F2 : TForm2; // --> Eğer değişken kullanmak zorundaysanız
begin
   { global veya yerel, bir değişkenimiz yok, alternatifi aşağıda
   Application.CreateForm(TForm2, Form2);
   Form2.Button2.Visible := True;
   Form2.Position := poMainFormCenter;
   Form2.ShowModal;
   Form2.Free;
   }

   { Eğer değişken kullanmak zorundaysanız
   F2 := TForm2.Create(Self) ; // SELF yerine NIL, APPLICATION da verebilirsiniz, bu kısım sizin araştırma konunuz olsun.
   with F2 do
   }

   with TForm2.Create(Self) do  // Oluşturma sırasında aşağıdaki işlemleri de peşisıra gerçekleştiriyoruz.
   try
     Button2.Visible := True;
     Position := poMainFormCenter;
     ShowModal; // MODAL olduğu için uygulamanın tamamı bu noktada işin bitmesini bekliyor.
   finally
     Free;      // MODAL'dan çıkıldığı an formu yok ediyoruz.
   end;
end;


procedure TForm3.Button2Click(Sender: TObject);
begin
  Close;
end;

end.

with TForm?.Create(Self) do yerine formlarınızda class function veya class procedure de tanımayabilirsiniz.
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#5
(07-12-2024, Saat: 14:28)uparlayan Adlı Kullanıcıdan Alıntı: Private veya public olması ile ilgili bir şey söylemedim ama ifadem yanıltıcı olmuş olabilir, 

Formları yönetmek çok geniş bir kavram olduğu için sadece sorunuz çerçevesindeki kısım ile sınırlı tutuyorum o nedenle detayları kodlar üzerinden açıklayayım.

Ön hazırlık olması ve kapanırken bellek sızıntısı oluşuyor mu oluşmuyor mu basitçe anlamak için .DPR dosyasındaki begin bloğuna aşağıdaki kodu ekliyoruz.

...
begin
  ReportMemoryLeaksOnShutdown := True;       // bellek sızıntıları varsa program kapanırken bir rapor göstersin.
  Application.Initialize;
...

Owner mekanizması denilen bir kavram var. Buna göre bir nesneyi oluştururken onun varlığını ve yokluğunu kontrol edecek bir sahip belirtmek gerekir. Dolayısıyla ana nesne yok edilirken ona bağlı alt nesneler de bu sayede otomatik olarak yok edilebilir.

unit Unit1;

interface
...
...

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses unit2, unit3;

procedure TForm1.Form21Click(Sender: TObject);
begin
  { artık global bir değişken (Form3) kullanmadığımız için bu kısım geçerli değil.
  Application.CreateForm(TForm3, Form3);
  Form3.ShowModal;
  Form3.Free;
  }


  with TForm3.Create(Self) do  // SELF = Bu nesne, yani bu durumda Form1 nesnesidir.
  try
    ShowModal;
  finally
    Free;
  end;

end;

{ bu sizin orjinal kodunuz;
procedure TForm1.Formlar2Click(Sender: TObject);
begin
  if Assigned(Form2) then
    Form2.show
  else
    begin
      Application.CreateForm(TForm2, Form2);
      Form2.FormStyle := fsMDIChild;
      Form2.Show;

    end;
end;
}

procedure TForm1.Formlar2Click(Sender: TObject);
var
  I: Integer;
  Form2Exists: Boolean;
begin
  Form2Exists := False;

  // Tüm MDIChild formları kontrol et
  for I := 0 to MDIChildCount - 1 do
  begin
    if MDIChildren[I] is TForm2 then
    begin
      Form2Exists := True;
      MDIChildren[I].Show; // Zaten varsa, göster
      exit;
    end;
  end;


  if not Form2Exists then
  begin
   with TForm2.Create(Self) do
   try
     FormStyle := fsMDIChild;
     Show;
   finally
     //Free; // doğrudan free etmiyoruz çünkü bu işi kullanıcı formun kapatma butonuna basarak kendisi manuel olarak gerçekleştirecek. detaylar TForm2.FormClose'da
   end;
  end;
end;

end.

2. forma gelelim;

unit Unit2;

interface
...
...


// Bu kısmı iptal edin.
//var
//  Form2: TForm2; // bu tanıma gerek yok

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
  { bu kısım anlamını yitirdi. 
  if Assigned(Form2) then
    ShowMessage('Assigned')
  else
    ShowMessage('not Assigned');
  }
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  Close;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := TCloseAction.caFree; // bu atamayı yaparak aslında FREE işlemini bu kısım VCL'in derinliklerinde gerçekleştiriyor zaten.
  //Form2 := Nil; // global bir değişkenimiz yok, o nedenle olmayan bir değişkenin referansını da artık sıfırlamamıza gerek yok.
end;

end.

3. forma gelelim;

unit Unit3;

interface
...
...

// bu kısmı iptal edin
//var
//  Form3: TForm3;

implementation

{$R *.dfm}

uses unit2;

procedure TForm3.Button1Click(Sender: TObject);
//var F2 : TForm2; // --> Eğer değişken kullanmak zorundaysanız
begin
   { global veya yerel, bir değişkenimiz yok, alternatifi aşağıda
   Application.CreateForm(TForm2, Form2);
   Form2.Button2.Visible := True;
   Form2.Position := poMainFormCenter;
   Form2.ShowModal;
   Form2.Free;
   }

   { Eğer değişken kullanmak zorundaysanız
   F2 := TForm2.Create(Self) ; // SELF yerine NIL, APPLICATION da verebilirsiniz, bu kısım sizin araştırma konunuz olsun.
   with F2 do
   }

   with TForm2.Create(Self) do  // Oluşturma sırasında aşağıdaki işlemleri de peşisıra gerçekleştiriyoruz.
   try
     Button2.Visible := True;
     Position := poMainFormCenter;
     ShowModal; // MODAL olduğu için uygulamanın tamamı bu noktada işin bitmesini bekliyor.
   finally
     Free;      // MODAL'dan çıkıldığı an formu yok ediyoruz.
   end;
end;


procedure TForm3.Button2Click(Sender: TObject);
begin
  Close;
end;

end.

with TForm?.Create(Self) do yerine formlarınızda class function veya class procedure de tanımayabilirsiniz.

Çok Teşekkür ederim çok açıklayıcı oldu kod örneği, geliştirmeye çalıştığım projede uyguladım fakat aldığım hata devam ediyor, bu kod ile basit şekilde tablo ile kurmaya çalıştığım yapının örneğini size göstererek değerlendirmek isterim çok vaktinizide almamış olmak adına,
Cevapla
#6
Kısaca, bu verdiğiniz örnekteki şekilde yaptım lakin bu kez form3 üzerinden form2 üzerindeki tabloya erişemiyorum Access Violation hatası üretiyor.
Cevapla
#7
Şöyle bir çözüm üretmeye çalıştım, form3 e design da datasource ekledim, design da iken datasource un dataset ine form2 deki tabloyu verdim, form3 üzerine eklediğim butonun onclick olauyına showmessage(DataSource1.DataSet.FieldByName('Code').AsString); yazarak datayı görüntüledim, datasource1.dataset üzerinden veriyi grid, edit vs. üzerine aktarabildim, izlenen yol doğrumudur bilmiyorum.
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  video player olan formu kapatma tekrar acma sorunu sadikacar60 3 131 26-11-2024, Saat: 16:39
Son Yorum: esistem
  Fonksiyon çağırma ermanispir@gmail.com 2 245 29-10-2024, Saat: 15:51
Son Yorum: ermanispir@gmail.com
  Aynı kayıt Mete 13 2.919 20-12-2022, Saat: 17:08
Son Yorum: ugorkem
  Kod İle Formu Create Etme sunbeki 9 2.389 06-12-2021, Saat: 11:16
Son Yorum: engerex
  Fastreport Sürekli Aynı Satırı çekiyor Anarchosa 3 1.599 27-05-2021, Saat: 23:57
Son Yorum: Anarchosa



Konuyu Okuyanlar: 1 Ziyaretçi