Tüm formları kapattırma

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
ulu coder
Üye
Mesajlar: 838
Kayıt: 01 Nis 2006 06:46
Konum: Ankara

Tüm formları kapattırma

Mesaj gönderen ulu coder »

viewtopic.php?t=15476
Bununla bi ilgisi yok.

File->New->Form diyerek oluşturduğum 14 adet formum var.
birincisi anaform, ikincisi görünmeyen bi form, diğerleri ara formlar.
AraForm'lardan biri açıldığında diğerleri kapansın diye bi fonksiyon yazdım;

Kod: Tümünü seç

Procedure FormAc(form:TForm);
Form3.Close;
Form4.Close;
Form5.Close;
...
Form14.Close;

Form.Show;//parametreye girileni aç
Bunu Find compenent ile yapmak isteyince Access Violation hatası verdi.
Yöntemim şuydu;

Kod: Tümünü seç

var
  i:integer;
begin
  For i:=3 to 14 Do TForm(FindComponent('Form'+inttostr(i))).Close;
end;
(Form'a bileşen diyip findcompenent kullanmak bana da saçma geldi)
Kullanıcı avatarı
lazio
Moderator
Mesajlar: 1527
Kayıt: 11 Tem 2003 04:55
Konum: İstanbul

Mesaj gönderen lazio »

Access Violation hatası vermesi çok doğal çünkü FindComponent() kendi içindeki sınıflara bakıyor ve bulamıyor. Bu durumda da null referansı Close etmeye çalışıyorsun. Birde FindGlobalComponent() dene..
DeveloperToolKit

..::|YeşilMavi|::..
Kullanıcı avatarı
Murat DİCLE
Kıdemli Üye
Mesajlar: 702
Kayıt: 19 Nis 2006 04:12
Konum: İstanbul
İletişim:

Mesaj gönderen Murat DİCLE »

Şimdi mantıken bu şekilde kapanma doğrudur, yapılabilir.

Ancak güvence koymak lazım programa, yani her halikarda 3..14 (11 adet form) açık mı? yoksa 3 ~ 14 nolu formlardan bazen tümü bazen bir kaçı mı açık olabiliyor. Eğer her zaman 3 ~14. nolu formlar her zaman aynı anda açık olma garantisi var ise senin yaptığın %100 doğru. Fakat hata verdi dediğine göre demekki o an create edilmemiş olan formlar var.

Şunu bir deneyelim.

Kod: Tümünü seç

var
   F : TForm;
   i : integer;
begin
   for i := 3 to 14 do
      begin
         F := TForm(FindCompnent('Form' + IntToStr(i)));
         if F <> nil then
            begin
               F.Close;
               // eğer OnClose'larında caFree demediysen
               F.Free;
            end;
      end;
end;
Bu kodlar güvenle 3 ~14 arasında açık olan formları kapatacaktır. Tabi bu işlemi farklı şekillerde yapmakta mümkün. Mesela Windows Mesajları ile ya da her create ettiğin formu TList'e ekler ve kapan işleminde sırayla Free edersin, buda mümkün. Hem bunun bir avantaşı daha olur, aynı formdan ikinci bir kez daha açılmayıda engeleyebilirsin. Tabi böyle bir şey istersen.

Yalnız şuna dikkat etmen gerekiyor. Burada formları nasıl luşturduğun önemlidir. TForm3 ~TForm14 sınıflarındaki formları Form3 ~Form14 tutamaçları ile oluşturuyorsan bir sorun yok.

Eğer içeriden kod olarak oluşturuyorsan TForm3 için mesela o zaman NAME kısmı boş olacağı için yukarıdaki kd bir işe yaramayacaktır. Diyelim ki sen TForm3 ila TForm14 formlarını bir buttona basınca şu şekilde oluşturuyorsun. Ve bir formdan bir kaç tane olma olasılığıda var diyelim. Yani ekranda istenirse birden fazla TForm14 sınıfından formlar olabilir.

Kod: Tümünü seç

procedure TForm1.YapForm1Click(Sender : TObject);
begin
   With TForm1.Create(Application) do Show;
end;

procedure TForm1.YapForm2Click(Sender : TObject);
begin
   With TForm2.Create(Application) do Show;
end;
.
.
.
procedure TForm1.YapForm14Click(Sender : TObject);
begin
   With TForm14.Create(Application) do Show;
end;
Eğer bu şekilde bir oluşum söz konusu ise ilk başta gösterdiğim örneği çöpe atmamız gerekiyor. O zaman öyle bir şey yapalım ki her halikarda işe yarayan bir şey olsun. Neredeyse sıfır hatasız bir sistem olsun. Garanti olsun. Bizim asıl amacımız TForm3 ~TFomr14 arasındaki formları kapatmak değil mi. Peki biz Form adları yerine Form'un sınıflarına göre bunu yapsak nasıl olur?

Kod: Tümünü seç

procedure TForm1.AlayiniKapat;
var
   i : integer;
   F : TForm;
begin
   for i := 0 to ComponentCount - 1 do
      if Components[i] is TFom then
         begin
            F := TForm(Components[i]);
            if (F.ClassName <> 'TForm1') and
               (F.ClassName <> 'TForm2') and
               (F.ClassName <> 'TForm3') then F.Close;
         end;
end;
Ne yaptık burada?
Burada bir TFORM sınıfından bir nesne bulduğumuzda bu formun TFORM1, TFORM2 ve TFORM3 haricinde olanları Close yaptık. Hani öyle olması istenmişti ya.

Açıkçası bu da tatmin edici değil benim için, evet programı biz yapıyoruz neyi ne zaman oluşturduğumuzu biz biliyoruz. Peki ileride bir 15. form yapsak ama bu 15. formun kapatılmaması gerekiyorsa ne yapacaz. Tabi yukarıdaki örnekteki IF satırına TFORM15'i de ekleyebiliriz. Ama bu uzar gider.

Görüldüğü gibi bir çok alternatif olmaktadır. Fakat en mantıklısı en hızlısını kullanmaktır. Tabi garanti olmasıda şarttır. Hadi o zaman son bir metod daha deniyelim. Aslında bunun sonu gelmez gibi geliyor bana, çok farklı kapatma yöntemleri bulmak mümkün.

Windows mesajı ile bunu yapalım.
Öncelikle bizim kuralımız gereği kapanması gereken tüm formların PRIVATE bölümüne

Kod: Tümünü seç

Private
   procedure Kapanmalisin(var M : TMessage); message WM_USER+99;
yazacağız.

Sonra Ctrl+Shift+C ile fonksiyonu oluşturalım ve bu mesaj fonsiyonunda da istediğimiz komutu yani CLOSE komutunu yazacağız.

TForm14 için örnek Örnek;

Kod: Tümünü seç

type
  TForm14 = class(TForm)
  .
  .
  private
    { Private declarations }
    procedure Kapanmalisin(var M : TMessage); message WM_USER+99;
  public
    { Public declarations }
  end;

var
  Form14: TForm14;
  Formlar : TList;

implementation
.
.
procedure TForm14.procedure Kapanmalisin(var M : TMessage); message WM_USER+99;
begin
   Close;
end;
.
.
.
Şimdi artık bu mesajı alabilen formların kapanma tetiği var. Ana form yada nerede istiyorsak kapanması gereken formlara mesaj çekmemiz gerekmektedir.

Kod: Tümünü seç

procedure TForm1.AlayiniKapat;
var
   i : integer;
begin
   for i := Screen.FormCount Downto 0 do
      PostMessage(Screen.Forms[i].Handle, WM_USER+99, 0, 0);
end;
İşte bu kadar, artık bu mesajı alan form içinde bunun tetiği var ise ilgili işlemi yapacaktır. Ben kodları denemedim, ama çok kere kullandım. Ezbere yazdığımdan yazım hataları olabilir. Varsa da siz mantığı anlamışsınızdır diye umuyorum.

Saygılar..
ulu coder
Üye
Mesajlar: 838
Kayıt: 01 Nis 2006 06:46
Konum: Ankara

Mesaj gönderen ulu coder »

@lazio'nun yardımıyla şu şekilde hallettim

Kod: Tümünü seç

For i:=3 to 14 do TForm(FindGlobalComponent('Form'+inttostr(i))).Close;
Bu ara formlardan en fazla biri açık.
Yazdığım prosedür de bunu sağlamak için.
Formx.show; yerine FormAc(x); diyorum, prosedür de önce hepsini (aslında, bi tanesini) kapatıyor, sonra parametredekini açıyor.

soruyu sorarken @muratdicle döktürecek şimdi demiştim :)
Tahminim doğru çıktı.
@Muratdicle'nin yöntemlerini başka sorunda kullanmak üzere kaydediyorum.

ikinize de teşekkürler.
Kullanıcı avatarı
lazio
Moderator
Mesajlar: 1527
Kayıt: 11 Tem 2003 04:55
Konum: İstanbul

Mesaj gönderen lazio »

ulu coder yazdı:@lazio'nun yardımıyla şu şekilde hallettim

Kod: Tümünü seç

For i:=3 to 14 do TForm(FindGlobalComponent('Form'+inttostr(i))).Close;
Yalnız bu durumda da @muratdicle nin dediği gibi bi kontrol uygulamanı tavsiye ederim :idea:
DeveloperToolKit

..::|YeşilMavi|::..
ulu coder
Üye
Mesajlar: 838
Kayıt: 01 Nis 2006 06:46
Konum: Ankara

Mesaj gönderen ulu coder »

lazio yazdı:
ulu coder yazdı:@lazio'nun yardımıyla şu şekilde hallettim

Kod: Tümünü seç

For i:=3 to 14 do TForm(FindGlobalComponent('Form'+inttostr(i))).Close;
Yalnız bu durumda da @muratdicle nin dediği gibi bi kontrol uygulamanı tavsiye ederim :idea:
Anladığım kadarıyla bu program için bütün çözümler sorunsuz.
Ne de olsa tüm formlar projenin açılmasıyla oluşturuluyor.
Ama günü kurtarmamak lazım, alışkanlık olsun, sağlama alalım, @muratdicle'nin son tavsiyesini uygulayayım.
ikra
Üye
Mesajlar: 901
Kayıt: 28 Nis 2005 01:26
Konum: Simdilik Topragin Üstü

Mesaj gönderen ikra »

dogru mu anladim bilmiyorum!

bir form acmak istediginde, o an acik olan diger form kapanmali.
ben su sekilde hallettim.
modal görünmeyen form lar kapatiliyor.

Kod: Tümünü seç

private
ActiveForm : string;
......................................
procedure CallForm(xForm : TComponentClass; var Reference; Modal : Boolean=False);
var zForm, cForm : TForm;
    FormName : string;
begin
FormName := copy(xForm.ClassName,2,length(xForm.ClassName));

zForm := Application.FindComponent(FormName) as TForm;
if not Assigned(zForm) then Application.CreateForm(xForm,Reference);

//aktif formu buluyoruz
cForm := Application.FindComponent(ActiveForm) as TForm;
zForm := Application.FindComponent(FormName) as TForm;

if Assigned(zForm) then
begin
  //aktif bir form var ise kapatiyoruz
  if not(modal) and (Assigned(cForm)) and (cForm.Name <> zForm.Name) then cForm.Close;
  //aktif olacak formu degiskene atiyoruz
  if not Modal then ActiveForm := zForm.Name;
  if Modal then
  try
    zForm.showmodal;
  finally
    FreeAndNil(zForm);
  end else
  begin
    zForm.Show;
  end;
end;
end;
Kodun yaptigi olay aynen su:
acilan ilk formu private de deklare edilen ActiveForm a kayit eder. eger gelen cagri Modal degil ise activeform u bulup kapatir ve acilmasi istenilen ikinci formu acar. acarken de activeform u yeni acilan formun ismi olarak degistirir.
umarim isini görür.
kolay gelsin
kıdemsiz üye
yusuf simsek
Üye
Mesajlar: 330
Kayıt: 09 Mar 2004 11:18
Konum: Konya
İletişim:

Re: Tüm formları kapattırma

Mesaj gönderen yusuf simsek »

Yukarıdaki ve benzer konu başlıkları altındaki kodlardan derleyerek yazıp kullandığım kodu paylaşmak istedim

Kod: Tümünü seç

procedure TAnasayfa.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
  i : integer;
  F : TForm;
begin
    if Application.MessageBox('Programı Kapatmak İstiyor musunuz?','UYARI',MB_YESNO+MB_ICONQUESTION) = mrno then
      Abort; // kapanmayı iptal ediyor...

  // MDI Formları kapatmak için
  if MDIChildCount > 0 then
    for  i := MDIChildCount - 1 downto 0 do
      begin
        MDIChildren[i].Close;
      end;

  // NORMAL Formları kapatmak için
  for i := 0 to Owner.ComponentCount - 1 do 
    if Owner.Components[i] is TForm then
       begin
          F := TForm(Owner.Components[i]);
          if (F.ClassName <> 'TAnasayfa') then // bu kontrolün amacı zaten form kapanış modunda olduğundan Kendisini kapatmamak... 
            F.Close;
       end;

Bugün bir kez daha,
Hiç Birşey Bilmediğimi Öğrendim!!!

https://extrayazilim.com
Cevapla