Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Form create hangisi daha doğru
#11
Kendi uyguladığım yöntem : 

Amaç : Process hafıza yönetimini ekonomik hale getirip kolaylaştırmak. Kullanıcı ilgili form(lar)a girmediği sürece hafızada yer işgal etmez, içlerindeki olası process üreten işler kapalı kalır.

Bir projemden örnek : 

1. Splash form Create yöntemi : Sizin belirttiğiniz ile aynı şekilde... Sadece OnClose ve OnDestroy olayları (4) ve (5) nolu adımdaki gibidir.
 SplashForm                 := TFormSplash.Create(nil);
 SplashForm.BorderStyle     := bsNone;
 SplashForm.Brush.Style     := bsClear;
 SplashForm.Image1.Left     := 0;
 SplashForm.Image1.Top      := 0;
 SplashForm.Width           := SplashForm.Image1.Width;
 SplashForm.Height          := SplashForm.Image1.Height;
 SplashForm.AlphaBlend      := True;
 SplashForm.AlphaBlendValue := 0;
 SplashForm.Show;
 With SplashForm do begin
   AlphaBlend      := True;
   AlphaBlendValue := 0;
   While AlphaBlendValue < 255 do begin
     Forms.Application.ProcessMessages;
     AlphaBlendValue := AlphaBlendValue + 5;
     Sleep(10);
   end;
 end;
 SplashForm.Update;

...
...
...
...
  SplashForm.Close;

2. Projeye eklenen formları (ana form hariç) DPR dosyasından mutlaka kaldırıyorum. ( bilgi için başlarına // comment tag ekliyorum )
       //Application.CreateForm(TFormArama, FormArama);
       //Application.CreateForm(TFormYapimHareketTarihDegistir, FormYapimHareketTarihDegistir);
       //Application.CreateForm(TFormAylikGrid, FormAylikGrid);
       //Application.CreateForm(TFormTalepOzeti, FormTalepOzeti);
       //Application.CreateForm(TFormBenzerTalepEkle, FormBenzerTalepEkle);
       //Application.CreateForm(TFormPreferences, FormPreferences);
       //Application.CreateForm(TFormYapimKoduModulu, FormYapimKoduModulu);
       //Application.CreateForm(TFormYapimTalep, FormYapimTalep);
       //Application.CreateForm(TFormStdTalep, FormStdTalep);
       //Application.CreateForm(TFormStdEkipman, FormStdEkipman);
       //Application.CreateForm(TFormYapimArama, FormYapimArama);
       //Application.CreateForm(TFormGorevliPersonel, FormGorevliPersonel);
       //Application.CreateForm(TFormPeriyodikTalep, FormPeriyodikTalep);
       //Application.CreateForm(TFormTalepIptal, FormTalepIptal);
       //Application.CreateForm(TFormPersonelBilgileri, FormPersonelBilgileri);
       //Application.CreateForm(TFormPersonelGorevSorgulama_TarihAraligi, FormPersonelGorevSorgulama_TarihAraligi);
       //Application.CreateForm(TFormYapimDagilimGrafigi, FormYapimDagilimGrafigi);
       //Application.CreateForm(TFormYolEmri_Ayarlar, FormYolEmri_Ayarlar);
       //Application.CreateForm(TFormYolYaziciNew, FormYolYaziciNew);
       //Application.CreateForm(TFormYolEmri, FormYolEmri);
       //Application.CreateForm(TFormStdPlnTarihler, FormStdPlnTarihler);
       //Application.CreateForm(TFormPersonelKayit, FormPersonelKayit);
       //Application.CreateForm(TFormKarsilastirmali, FormKarsilastirmali);
       //Application.CreateForm(TFormHizmetDegistir, FormHizmetDegistir);
       //Application.CreateForm(TFormHizmetTanimlari, FormHizmetTanimlari);
       //Application.CreateForm(TFormHizmet_YeniHizmet, FormHizmet_YeniHizmet);
       //Application.CreateForm(TFormSMSHarekeleri, FormSMSHarekeleri);
       //Application.CreateForm(TFormGorevlendirme, FormGorevlendirme);
       //Application.CreateForm(TFormSaatTashih, FormSaatTashih);
       //Application.CreateForm(TFormKisiyeSMS, FormKisiyeSMS);
       //Application.CreateForm(TFormHizmetFiyatlandirma, FormHizmetFiyatlandirma);
       //Application.CreateForm(TFormEkipmanAtama, FormEkipmanAtama);
       //Application.CreateForm(TFormKurguTarihSaat, FormKurguTarihSaat);
       //Application.CreateForm(TFormMaliyetRapor, FormMaliyetRapor);
       //Application.CreateForm(TFormSQLGen, FormSQLGen);
       //Application.CreateForm(TFormSaatTashih, FormSaatTashih);
       //Application.CreateForm(TForm1, Form1);
       //Application.CreateForm(TFormAyarlar, FormAyarlar);
       //Application.CreateForm(TForm2, Form2);
       //Application.CreateForm(TFormYapimYonetimYardimci, FormYapimYonetimYardimci);
3. Proje içerisinde formlardan birine erişim olacaksa şöyle bir kod ile erişiyorum. ( @Mr.Developer ile aynı method ) 

      if NOT Assigned(FormServis) then
        Application.CreateForm(TFormServis, FormServis);
      FormServis.ShowModal;

4. Eriştiğim form içerisinde ( tüm formlar için geçerli ) OnClose olayında aşağıdaki kod çalışıyor.
procedure TFormServis.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

5. Eriştiğim form içerisinde ( tüm formlar için geçerli ) OnDestroy olayında aşağıdaki kod çalışıyor.
procedure TFormServis.FormDestroy(Sender: TObject);
begin
  FormServis := Nil;
end;
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#12
@mrmarman hocam Formu nil etme eventı olarak neden Destroyu kullanıyorsunuz;? Ben onclose a yazıyorum. Mantıksal olarak farkı nediR?
// Bilgi paylaştıkça çoğalır.. 

Cevapla
#13
(06-12-2020, Saat: 12:29)tuna Adlı Kullanıcıdan Alıntı:
(06-12-2020, Saat: 00:11)mustafaozpinar Adlı Kullanıcıdan Alıntı: Selam,
Aslında neyi sormak istediğinizi tam olarak anlayamadım. Anladığım kadarıyla fikrimi söyleyeyim;
İkisi arasında işlem olarak bir fark yok, birinde Form pointer'ini Heap'te diğerini ise stack'te tutuyor. Ancak; Bir nokta var ki 1. kullanımı eski moda haline getiriyor. 1. kullanım zaten Delphi'nin programcıya açılışta önerdiği yöntem. Diğeri ise bazı tasarım kalıpları kullanımı ile zenginleştirilerek çok esnek, birbirine bağlı olmayan (decoupled) formlar tasarlamaya kadar götürür bizi...

Yorumlarınız için çok teşekkür ederim.
Sormak istediğim aslında bu form create yöntemini delphinin uzmanı olan hocalarımız nasıl kullanıyor. Onlarında mutlaka kendilerine göre kullandıkları yöntemler vardır.
Bu sorduğum aslında bir soru değil tamamen tavsiyeleri almak.

Ben bir uygulamada şu şekilde kullandım,
1- Öncelikle MainForm ve diğer formları birbirinden ayırdım. Yani MainForm diğer hiç bir formu Used listesinde kullanmayacak. Peki bunu nasıl yapacağım. Öncelikle formları sınıfladım, a) Liste formları: Bunlar üzerinde bir DBGrid (ya da türevi başka gridler) ve Ekle-Düzelt-Sil-DetayGöster butonları var ayrıca Raporlama vs de olabilir, ama hepsinde ortak olan bunlar. b) Edit formları: Bunlar bir Liste formu üzerinde seçilen bir kayıtı gönderip düzeltme yapıp OK veya CANCEL tuşlarıyla düzeltme işini belirttiğimiz bir form. 
c) Seçim formları: Bunlarsa genelde giriş ekranlarında bir kod için LookupCombo kullanmak yerine yine kodların listesini getirip üzerinden birini seçmemizi sağlayan formlar.
d) Son olarak da; MainForm, zaten bu tek bir adet form oluyor.
Ben bunların ilk üçü için TemplateForm, TemplateEditForm, TemplateBrowseForm adında taslak formlar oluşturdum ve programda kullandığım tüm formları da bunlardan türettim.
Sonuçta bu çok faydalı oldu, çünkü pek çok işi bu taslakta yaptırdığım için nihai formların işleri çok azaldı, ayrıca bana taslak uyarı da vermeye başladı. Çünkü bazı metotları abstract tanımlamıştım, bunlar hata göndermeye başladı. 

Bunlar tamam, eyvallah; ama bunlar yaratım şekillerini etkilemez. Ayrıca decoupled olmasını da sağlamaz. Bunu nasıl sağlayacağım. İşte bunun için formları isimlerine göre tuttuğum 2 ayrı factory oluşturdum. Biri liste için diğeri ise edit formları için. Yani amaç bunların değişkenlerinin adını yazarak açmak kapatmak değil fabrikasyon nesnesine ismi A olan formu aç şeklinde komut göndererek açmak olacak.

  Form1 := TForm1.Create(Application);
  ...
  Form1.Show; 
  //veya
  Form1.ShowModal;
  //yerine
  form1 := MyFactoryListForm.GetForm('TSupplierListForm');
  

Şeklinde kullanarak TSupplierListForm ismiyle factory'ye Create metodu kaydedilmiş formu yaratıp açmak.

Tabi her form unit'inin altında da initialization kısmında bu form tiplerinin factory'ye bu isem ve Create metoduyla birlikte kaydedilmesi gerekiyor.

unit View.SupplierList;
interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, View.TemplateForm, Data.DB,
  Vcl.StdCtrls, Vcl.Grids, Vcl.DBGrids, Vcl.ExtCtrls, Vcl.Menus;

type
  TSupplierListForm = class(TTemplateForm)
  private
    { Private declarations }
  protected
    procedure OpenDataset; override;
    function GetEditFormName : string; override;
  public
    { Public declarations }
  end;

var
  SupplierListForm: TSupplierListForm;

implementation
uses MainDM,
     Model.Declarations,
     Support.LanguageDictionary,
     Support.FabricationListForm;

{$R *.dfm}

{ TTemplateForm1 }

function TSupplierListForm.GetEditFormName: string;
begin
  Result := 'TSupplierEditForm';
end;

procedure TSupplierListForm.OpenDataset;
begin
  fDataSet := DMMain.MySession.GetList(TSupplier, '');
end;
var
  CreateForm : TFactoryMethodListForm<TTemplateForm>;

initialization

  CreateForm := function : TTemplateForm
     begin
       if not DMMain.IsUserAuthorized('1020,1021,1022,1023,1024') then  // DataModul'de kullanıcının bu işi yapabilir mi diye kontrol edildiği bölüm
         raise Exception.Create(Support.LanguageDictionary.MessageDictionary().GetMessage('SNotAuthorized')+#13#10+'TSupplierListForm'); // Hata mesajı dışarıdan alınıyor, değişik diller kullanılmasını olanaklı kılıyor
       Result := TSupplierListForm.Create(Application);   // Ve nihayet Create!!!
     end;

  MyFactoryListForm.RegisterForm<TSupplierListForm>('TSupplierListForm', CreateForm);
end.
Gördüğünüz gibi SupplierListForm bomboş. Neredeyse tüm işleri Temlate form yapıyor.

type
  TTemplateForm = class(TForm)
    Panel11: TPanel;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    Panel1: TPanel;
    btnAdd: TButton;
    btnEdit: TButton;
    btnDelete: TButton;
    btnView: TButton;
    popupmnuGrid: TPopupMenu;
    menutemGridProperties1: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure DBGrid1DblClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormDestroy(Sender: TObject);
    procedure btnAddClick(Sender: TObject);
    procedure btnEditClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
    procedure btnViewClick(Sender: TObject);
    procedure menuitemGridProperties1Click(Sender: TObject);
  private
    FOkToClose : Boolean;
  protected
    fDataset : TDataset;
    procedure FormLoaded; virtual;
    procedure UpdateLabelsText; virtual;
    procedure OpenDataset; virtual; abstract;
    procedure DeleteCurrent; virtual;
    procedure Print; virtual; abstract;
    function PrepareEditForm(cmd : TBrowseFormCommand) : TTemplateEdit; virtual;
    function GetPKName : string; virtual;
    function GetEditForm(ACmd: TBrowseFormCommand): TTemplateEdit;
    function GetEditFormName : string; virtual; abstract;
  public
    procedure Refresh; virtual;
    procedure OrderCommand(command : TBrowseFormCommand; var res : Variant); virtual;
  end;

Şu şekilde bir factory nesnesi oluşturdum,

  TFactoryMethodListForm<TBaseType> = reference to function: TBaseType;

  TFactoryListForm<TKey, TBaseType> = class
  private
    fFactoryMethods: TDictionary<TKey, TFactoryMethodListForm<TBaseType>>;
    function GetCount: Integer;
  public
    constructor Create;
    property Count: Integer read GetCount;
    procedure RegisterFactoryMethod(key: TKey; factoryMethod: TFactoryMethodListForm<TBaseType>);
    procedure UnregisterFactoryMethod(key: TKey);
    function IsRegistered(key: TKey): boolean;
    function GetInstance(key: TKey): TBaseType;
  end;


  TMyFactoryListForm = class
    FormFactory: TFactoryListForm<string, TTemplateForm>;
    constructor Create;
    procedure RegisterForm<T>(const TypeName : string; aFunc : TFactoryMethodListForm<TTemplateForm>);
    function GetForm(const TypeName : string) : TTemplateForm;
  end;

var
  MyFactoryListForm : TMyFactoryListForm;

implementation

constructor TMyFactoryListForm.Create;
begin
  inherited;
  FormFactory:= TFactoryListForm<string, TTemplateForm>.Create;
end;

function TMyFactoryListForm.GetForm(const TypeName: string): TTemplateForm;
begin
  Result := FormFactory.GetInstance(TypeName);
end;

Tabi ki bu projede ayrıca bir de mini ORM benzeri bir yapı kullandım. O da işleri ciddi şekilde kolaylaştırıyor. Tabii ki bunun yerine çok daha gelişkin ORM'ler mevcut onları kullanmak daha akıllıca olabilir. Benimkisi kendim yaptığım için bedava. Henüz bedava olup istediğimi yapabilen bir ORM bulamadım. Aslında bir adet var, Marshmallow, fakat o da Spring4d üzerinde yazıldığı için Rest kullandığınızda sorun çıkarıyor. Yeni bir bileşen seti buldum onu deneyeceğim, beğenirsem onu kullanacağım.

  TMyConnection = class
  public
    function AppendRecord(AEntity : TObject) : Boolean; overload; virtual; abstract;
    function AppendRecord(AClass : TClass; ASourceDS: TDataset; const AAllRecords: Boolean = false) : Boolean; overload; virtual; abstract;
    function UpdateRecord(AId : Integer; AEntity : TObject) : Boolean; overload; virtual; abstract;
    function UpdateRecord(AClass : TClass; AId : Integer; ASourceDS: TDataset; const AAllRecords: Boolean = false) : Boolean; overload;  virtual; abstract;
    function DeleteRecord(AClass : TClass; AId : Integer) : Boolean;  virtual; abstract;
    function GetList(AClass : TClass; const AFilter : string;ASelect: string='*'; const AOrderBy : string = '') : TDataset; overload;  virtual; abstract;
    function GetList(AClass : TClass; const AFilter : string; AParams: Array of Variant; AParamTypes: Array of TFieldType;
                  ASelect: string='*'; const AOrderBy : string = '') : TDataset; overload;  virtual; abstract;
    function GetList(const ASql : string; const AParams : Array of Variant; const ATypes: array of TFieldType) : TDataset; overload;  virtual; abstract;
    function GetRecord(AClass : TClass; id : integer; select: string='*') : TDataset; overload;  virtual; abstract;
    function GetRecord(AClass : TClass; const where : string; const AParams : Array of Variant; ATypes: array of TFieldType;
                       select: string='*') : TDataset; overload;  virtual; abstract;
    function ExecSql(const ASql : string; AParams : array of Variant; AFieldTypes: array of TFieldType) : boolean; virtual; abstract;
    function TableName(AClass : TClass): string;  virtual; abstract;
    ...
  end;

Umarım size yardımcı olur! Daha detay bilgi isterseniz gönderebilirim. Yani bunlar gizli saklı şeyler değil.
Cevapla
#14
@mustafaozpinar

- Yazılımcının kaynak kodlarını paylaşması evdeki yatak odasına tamirci/boyacı gelince hissettirdiklerine denk olduğundan sakınca aslında mahrem kavramında saklı  Smile  Düzeni veya kod terbiyesini açık eder.

@mcuyan  

OnClose olayında tüm işlemler bittikten ve form kapatıldıktan sonra OnDestroy olayı devreye girer. Yani burada detay form kapatılmış olması.  

OnCreate eventinde ne yapıyorsak ve OnShow ile form oluştuktan sonra işlemleri yapıyorsak,  OnDestroy olayını bunun parantezin kapatılması gibi değerlendirin.

Formdaki nesnelerin ve dolayısıyla karşılık gelen hafıza bloğunun boşaltılması için OnDestroy en uygun yerdir.
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#15
(06-12-2020, Saat: 14:17)mcuyan Adlı Kullanıcıdan Alıntı: @mrmarman hocam Formu nil etme eventı olarak neden Destroyu kullanıyorsunuz;? Ben onclose a yazıyorum. Mantıksal olarak farkı nediR?
Sayın mcuyan,
Close ayrı, Destroy ayrıdır. Bir formu Close ettikten sonra tekrar Show yapıp Close edebilirsiniz. Bu durumda program patlar. Yani mutlaka Destroy'da yapmanız gerekir.
Cevapla
#16
Çok teşekkür ederim bilgiler için.
// Bilgi paylaştıkça çoğalır.. 

Cevapla
#17
Verilen cevaplar için çok çok teşekkürler. Gerçekten bilmediğimiz o kadar çok şey varki.
Böyle konular açarak ufkumuzu genişletmeye devam edelim bence.
Cevapla
#18
Bir nokta eksik kalmış, değinmezsek yetim kalır
Modal olarak kullandığınız formlar için eğer "gerekmiyorsa" değişken tanımlamadan da onları kullanabilirsiniz. Fakat Modal olarak açacağınız formun MDIChild bir form olma-ması gerekir. Şu şekilde de kullanabilirsiniz mesela TForm1 diye bir formunuz olsun, en basitinden şöyle de kullanılabilir;

with TForm1.Create( aOwner ) do // veya Self veya Application, artık o anki duruma göre
try
  Caption := 'Modal Form için bir başlık';  // Bu TForm1 nesnesinin başlığıdır... TForm1 nesnesindeki öğelere nasıl erişeceğinizi gösterir.

  //... TForm1 formu ile ilgili diğer ayarlamalarınız ve kodlarınız
  //... TForm1 formu ile ilgili diğer ayarlamalarınız ve kodlarınız
  //... TForm1 formu ile ilgili diğer ayarlamalarınız ve kodlarınız
  
  ShowModal;  // Buraya kadar olan kısım FormCreate olayından sonra fakat FormShow olayından önce gerçekleşir.
  // Eğer TForm1 nesnesinde sonuç değeri çekmek istiyorsanız bunu bu noktada da yapabilirsiniz. 
  // Sonrasında formu yok etmeniz gerekir... Formu kapattığınızda (ShowModal'dan hemen sonra) onClose olayı bu noktada gerçekleşir
finally
  Free; // Bundan hemen önce de OnDestroy olayı tetiklenir.
end;
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


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  server programinda hani veritabani dogru olur. sadikacar60 4 346 30-01-2024, Saat: 21:06
Son Yorum: sadikacar60
  Optik form kodlama baloglurecep 8 1.305 16-11-2023, Saat: 16:23
Son Yorum: COMMANDX
  Edit içindeki tarihin doğru olup olmadığını kontrol etmek? hasansavci 2 390 17-10-2023, Saat: 03:35
Son Yorum: mcuyan
Sad Tabsheet içinde Form Create, Close olayları YILDIRIMBEY 0 250 24-08-2023, Saat: 17:26
Son Yorum: YILDIRIMBEY
  Runtime Form Oluşturmak ermanispir@gmail.com 5 1.129 02-08-2023, Saat: 09:31
Son Yorum: SimaWB



Konuyu Okuyanlar: 1 Ziyaretçi