Ş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..