İyi günler. Burada sanırım hem form sınıfı hem de o forma ait değişkenin takibi paralel olarak yapılmak istenilmektedir. Eğer sadece sınıfa bağlı olarak sınırsız form açılmak istenseydi iş çok kolaydı aslında sadece RegisterClass-FindClass fonksiyonları iş görürdü. Eğer
TForm1 sınıfı oluştuğunda veya yok edildiğinde
var Form1:TForm1; değişkenini de etkileyecekse işler biraz kontrol kodları eklemeye bağlı olarak yine çözümlenebilir. Mesela .dpr projenizde tanımlı unitlerin en başına aşağıdaki
untFormlar.pas unit'ini ekleyelim. Örnek .dpr aşağıdaki gibi olacaktır.
program Project1;
uses
Vcl.Forms,
untFormlar in 'untFormlar.pas',
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2},
Unit3 in 'Unit3.pas' {Form3};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.untFormlar.pas dosyası:
unit untFormlar;
interface
uses System.SysUtils, Vcl.Forms, System.Generics.Collections;
type
TAtaForm=class(TForm)
private
procedure DoCreate;override;
procedure DoDestroy;override;
procedure DoClose(var Action: TCloseAction); override;
end;
TFormBilgisi=record
FormSinifi:TFormClass;
FormDegiskenAdresi: Pointer;
end;
TFormBilgileri=TList<TFormBilgisi>;
var FormBilgileri:TFormBilgileri;
function indexOfFormClass(const fsFormSinifi:TFormClass):Integer;overload;
function indexOfFormClass(const sFormSinifiAdi:String):Integer;overload;
function FormSinifiEkle(const fsFormSinifi:TFormClass;const pFormDegiskenAdresi: Pointer):Integer;
function FormAc(const sFormSinifAdi:String):TForm;
implementation
function indexOfFormClass(const fsFormSinifi:TFormClass):Integer;
var bAramaYap:Boolean;
begin
Result:=FormBilgileri.Count-1;
bAramaYap:=True;
while bAramaYap and (Result>=0) do begin
if fsFormSinifi=FormBilgileri[Result].FormSinifi then
bAramaYap:=False
else Dec(Result);
end;
end;
function indexOfFormClass(const sFormSinifiAdi:String):Integer;
var bAramaYap:Boolean;
begin
Result:=FormBilgileri.Count-1;
bAramaYap:=True;
while bAramaYap and (Result>=0) do begin
if SameText(sFormSinifiAdi, FormBilgileri[Result].FormSinifi.ClassName) then
bAramaYap:=False
else Dec(Result);
end;
end;
function FormSinifiEkle(const fsFormSinifi:TFormClass;const pFormDegiskenAdresi: Pointer):Integer;
var fbFormBilgisi:TFormBilgisi;
begin
Result:=indexOfFormClass(fsFormSinifi);
if (Result<0) then begin
fbFormBilgisi.FormSinifi:=fsFormSinifi;
fbFormBilgisi.FormDegiskenAdresi:=pFormDegiskenAdresi;
Result:=FormBilgileri.Add(fbFormBilgisi);
end;
end;
function FormAc(const sFormSinifAdi:String):TForm;
var iYer:Integer; fbFormBilgisi:TFormBilgisi;
begin
Result:=nil;
iYer:=indexOfFormClass(sFormSinifAdi);
if iYer>=0 then begin
fbFormBilgisi:=FormBilgileri[iYer];
Result:=TForm(fbFormBilgisi.FormDegiskenAdresi^);
if not Assigned(Result) then begin
Result:=fbFormBilgisi.FormSinifi.Create(Application);
end;
Result.Show;
end;
end;
{ TAtaForm }
procedure TAtaForm.DoClose(var Action: TCloseAction);
begin
Action:=caFree;
inherited;
end;
procedure TAtaForm.DoCreate;
var iYer:Integer; pFormAdresi: Pointer;
begin
inherited;
iYer:=indexOfFormClass(TFormClass(Self.ClassType));
if (iYer>=0) then begin
pFormAdresi:=FormBilgileri[iYer].FormDegiskenAdresi;
if not Assigned(TForm(pFormAdresi^)) then
TForm(pFormAdresi^):=Self;
end;
end;
procedure TAtaForm.DoDestroy;
var iYer:Integer; pFormAdresi: Pointer;
begin
iYer:=indexOfFormClass(TFormClass(Self.ClassType));
if (iYer>=0) then begin
pFormAdresi:=FormBilgileri[iYer].FormDegiskenAdresi;
//if Assigned(TForm(pFormAdresi^)) then -> hatalı
if (Self=TForm(pFormAdresi^)) then
TForm(pFormAdresi^):=nil;
end;
inherited;
end;
initialization
FormBilgileri:=TFormBilgileri.Create;
finalization
FormBilgileri.Free;
end.
Artık kayda geçilecek bütün formların atası olarak
TAtaForm'u verip initialization bloğunada bir kayıt yapan satır eklemekle istediğiniz yapı kurulacaktır. Mesela projede bulunan böyle formlardan birisi
TFormX olsun.
unit untFormX;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, untFormlar;
type
TFormX = class(TAtaForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
FormX: TFormX;
implementation
{$R *.dfm}
initialization
FormSinifiEkle(TFormX, @FormX);
end.Bu şekilde
TAtaForm'dan türeyen ve
initialization bloğunda kayda geçilen sınıf ve sınıfa ait değişkeni artık aşağıdaki gibi kullanabiliriz. Üstelik
uses satırına çağırdığımız forma ait uniti eklememiz de gerekmemektedir. Her form oluştuğunda (mesela TFormX) ilgili forma ait (FormX) değişkene oluşan form atanır veya yok edildiğinde
nil ataması gerçekleşecektir. Bütün bunları TAtaForm sınıfı organize ettiği için formların bu sınıftan türemesi şarttır. Bu formlardan birisini kullanmak için ise sadece
FormAc('TFormX'); demek yeterli olacaktır. Eğer siz daha sonra
FormX.Free;
yazsanız bile
AtaForm,
FormX değişkenine nil değeri atayacaktır. İyi çalışmalar.