Haberler:

Vip Üyelere özel Program İndir kategorisi altına Windows 10 Enterprise 64 Bit indirme linki eklenmiştir.

Ana Menü

Delphide Formlarla Çalışmak

Başlatan Safirmedya, 06 Mart , 2011, 22:16:02

« önceki - sonraki »

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.

Safirmedya

Windows tabanlı programlar genellikle pencere içinde çalışırlar. Delphi literatüründe bu
çalışma pencereleri form olarak adlandırılırlar.  Bir delphi programı genellikle bir veya
birkaç formun birbirine bağlanması ile oluşur. Bu yazıda formların özellikleri, türleri ve
kendileri hakkında bilinmesi gereken önemli bilgilerle birlikte, ilave olarak formlar arasında
bilgi transferinin nasıl yapılacağı ve formların birbirine nasıl bağlanacağı konuları üzerinde
duracağım.
Başlamadan önce sizlere delphi ile çalışırken ihtiyacınız olabilecek ve işinizi daha
kolaylaştıracak bazı ip uçları vermeye çalışayım. Ayrıca başlangıçta dikkat ettiğinizde
projelerinizin ileriki dönemlerinde işinizi kolaylaştıracak bazı bilgileri de burada
bulacaksınız.
Öncelikle bir projeye başlamadan önce, bu projeyle ilgili bütün dosyaları içinde tutacağınız
bir klasör açın. Ben genellikle belki gözümden bir şey kaçar diye bu klasörü kök dizinde
açıyorum. Çünkü proje bittiğinde kullanıcılara dağıtılması gerekir. Kullanıcıları da sizin
kullandığınız klasörü kullandırmaya yönelirseniz oluşabilecek bazı hataları daha ortaya
çıkmadan önlemiş olursunuz. Bu sitede üzerinde çalışacağımız bütün örnekler için C: sürücüsünün
kökünde oluşturduğum ve adı WORK olan bir dizin kullanacağım. Eğer projenizde veritabanı
dosyaları kullanacaksanız bu dosyalarınızın program kaynak dosyaları ile karışmaması için
çalışma dizininizin içinde ( benimki C:\WORK) DATA diye bir dizin oluşturmanız yararınıza olur.
Ben genellikle 1024x768 çözünürlükte çalışıyorum. Eğer ekran kartınız müsaade ediyorsa sizde en
az bu çözünürlükte çalışmaya özen gösterin. Aslında 1024x768 uygun bir çözünürlüktür, bu
çözünürlükte çalışırken form için kullanabileceğiniz alan 800x600 ebadında bir form için
yeterlidir. Ve genellikle kullandığınız formlar için en fazla 800x600 boyutlarını kullanın.
Çünkü programınızı kullanan herkesin yüksek çözünürlükleri destekleyebilecek bir ekran kartı
veya zevki olmayabilir.
Kendiniz için bazı kurallar koyun. Mesela formlarınızın isimleri Delphi'nin standart
isimlerinden Form1, Form2, ... gibi isimleri kullanmak yerine her zaman bu formlarınıza
aklınıza kolay gelebilecek isimler koyun. Formlarınıza Frm ile başlayan isimler koymanız
uygun olur. Bunu kendiniz için bir standart haline getirdiğinizde ilerleyen dönemlerde
işlerinizin daha da kolaylaştığını göreceksiniz.
Eğer mümkünse ana form üzerine açılan formlarınızın boyutu ana formunuzdan daha küçük olsun.
Delphi'de Çok Formlu Uygulamalar
Tek bir form ve birkaç bileşenle tamamen işlevsel uygulamalar geliştirilmesi mümkün olsa da,
birden fazla forma sahip olan uygulamalara çok daha fazla rastlanır.  Aslında pratik olarak
delphi uygulamalarınızı geliştirebilmeniz için iki farklı form tekniği kullanır. Bunlardan
birincisine örnek olarak Microsoft Word uygulamasında olduğu gibi ana bir pencere çerçevesi
içinde bu pencere tarafından oluşturulmuş birden fazla pencerenin var olabileceği MDI olarak
adlandırılan formlar vardır. İkinci form şekli ise Ana form tarafından oluşturulan ancak ana
form içinde yer almayan birden fazla formların kullanıldığı uygulamalardır. Birkaç örnek
olarak Paint, WordPad, Notepad gibi  uygulamaları gösterebiliriz.  Bu yazımızda ikinci
tekniği kullanacağız . Bir programın içinde bir çok form vardır. Bu formlardan bir tanesini
uygulama çalıştığında görüntüye gelen form oluşturur. Bu form ana form olarak nitelendirilirse
diğer formlar bu ana formdan türerler.
Şimdi yazacağımız uygulamada bir ana form ve bu ana form tarafından oluşturulacak 3 tane
form olacak. Bunun için Delphi'yi çalıştırın ve karşınıza gelen Form1 formuna ilave olarak
üç tane daha form ilave edin. Şimdi ilk olarak neye dikkat etmemiz gerektiğine bakalım.
Project | Options menüsünü çalıştırdığınızda karşınıza Project Options penceresi gelir.
Bu pencerenin bizim programımız için görünümü aşağıdaki gibiydi.
Kaynak :
Marco Cantû, Herkes İçin Delphi 3
Steve Teixeira & Xavier Pacheco, Borland Delphi 4 Developer's Guide
Yukarıdaki görüntüye dikkat ettiğinizde ilk göze çarpan Main form olarak Form1'in tanımlı
olduğudur. Bunun anlamı programı çalıştırdığınızda sadece Form1 görüntüye gelecek.
Auto-create forms başlığı altında ise program çalıştığında otomatik olarak yaratılacak
formların listesini görüyoruz. Bizim tanımladığımız diğer formlar program çalıştığında
görüntüye gelmediği halde otomatik olarak yaratılıyor. Bize düşen sadece gerektiğinde
bu formları görüntüye getirecek komutu gerekli yere yazmaktır. Ancak otomatik olarak
yaratılan formların sayısı arttığı müddetçe bu formların hafızada kapladıkları toplam
alan oldukça yüksek bir değere ulaşır. Bu doğru bir mantık değildir.
program Project1;
uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2},
  Unit3 in 'Unit3.pas' {Form3},
  Unit4 in 'Unit4.pas' {Form4};
{$R *.RES}
begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TForm2, Form2);
  Application.CreateForm(TForm3, Form3);
  Application.CreateForm(TForm4, Form4);
  Application.Run;
end.
Yukarıdaki kodlar projemizin formları oluştururken kullandığı kodlardır. Bu kodlara dikkat
ederseniz bütün formlar yaratıldıktan sonra uygulama çalıştırılıyor. Dolayısı ile bütün
formların oluşturulması programın ilk çalışma anını uzatıyor.
Program çalışırken görünen formun dışındaki formlar hafızada yaratılmış şekilde durduğunda
bu formların görüntüye getirilip kapatılması (gizlenmesi) son derece hızlı olur ancak bu
aşırı hız hafıza problemini de beraberinde getirmektedir. Ana formumuz  Form1 olduğuna göre
diğer formları Available forms bölümüne aktarmamız daha mantıklıdır. Böylece programımız
çalıştığında sadece Form1 yaratılacak ve görüntülenecek. Diğer formlar ise ihtiyaç
duyulduklarında yaratılmak ve görüntülenmek için hazır durumda bekleyecekler. Bu şekilde
kurulan bir yapıda hafıza tasarrufu daha rahat yapılabilir. Gerekli düzenlemeyi yaptıktan
sonraki Project Options penceresinin görünümü ve projenin kaynak kodu aşağıdaki gibi olur.
program Project1;
uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2},
  Unit3 in 'Unit3.pas' {Form3},
  Unit4 in 'Unit4.pas' {Form4};
{$R *.RES}
begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
Proje kodunun son haline dikkat ettiğimizde program çalışmadan önce sadece Form1 oluşturulmuş.
Form1 isimli forma diğer üç formla bağlantı kurabilmek için üç tane button yerleştirdim. Ana
form olarak kullandığım formun görünümü aşağıdaki gibidir.
Button2'ye basıldığında Form2, Button3'e basıldığında Form3, Button4'e basıldığında Form4
görüntülenecek. Button1'i programı kapatmak için kullanacağız. Bunun için Button1'in üzerine
Kapat yazdım.
İlk olarak Kapat buttonunun görevini hazırlayalım. Bir pencereyi kapatmanın birçok yolu vardır.
Eğer kapatılan pencere ana form olarak tanımlıysa bu aynı zamanda programın çalışmasının sona
ermesine sebep olur.  Bunun için gerekli kodu Kapat button'unun onclick olayına yazdım. Kod
aşağıdaki gibidir.
procedure TForm1.Button1Click(Sender: TObject);
begin
Application.Terminate;
end;
Application.Terminate satırına sadece Close veya Form1.Close yazmak da aynı şeyi yapıyor.
Bunun sebebi ana pencereyi kapatmakla uygulamayı sonlandırmanın aslında aynı şey olduğudur.
Şimdi Button2 düğmesine Form2'yi görüntüye getirecek kodu yazalım. Ama daha önce Form2 formuna
da bir kapat button'u yerleştirip bu button'un onClik olayına Form2.Close veya sadece Close
yazalım ki uygulamayı çalıştırıp Form2'yi görüntülediğimizde tekrar kapatabilelim. Button2
düğmesinin onClick olayına aşağıdaki kodları sırayla yazalım ve her kodun ne anlama geldiğini
görelim.
procedure TForm1.Button2Click(Sender: TObject);
begin
Form2:=TForm2.Create(Form1);  //1 Form1 ifadesi yerine Application yazabilirsiniz.
Form2.Showmodal;              //2
Form2.Free;                   //3
end;
Öncelikle Form2'yi görüntüye getirmek için yaratılması lazım. (1) numaralı satır Form2'yi
yaratıyor parantez içindeki (Form1) ifadesi ise Form2'nin kim tarafından yaratıldığını
gösteriyor. Bizim örneğimizde Form2'yi Form1 yarattığı için buraya Form1 yazdım. Bu parametreye
genelde fazla dikkat edilmez ancak çok önemlidir. Mesela yaratılan ikinci formun kendisini
oluşturan formun ekrandaki pozisyonu ne olursa olsun tam ortasına gelmesini istiyorsak
Form2'nin Position özelliğini poDesigned değil de poOwner FormCenter yaparsak istediğimiz
olur. Form1'i çalışma modunda iken istediğiniz yere taşıyın Button2'ye basmanız Form2'yi tam
Form1'in ortasında gösterir.
İkinci numaralı satırda Form2'yi modal olarak görüntüledik. Bunun anlamı Form2 kapatılmadan
önce, Form2'yi oluşturan formun disable durumda olacağıdır. Yani daha başka bir ifade ile
Form2 kapatılmadan Form1'deki hiçbir görsel bileşen kullanılamaz.
Üçüncü satırda ise Form2 modal olarak gösterildikten sonra Form2'nin kapatılmasını takiben
onu hemen hafızadan silmemizi sağlayan Free komutu kullandık. Bu komutu kullanmadığımızda
program gene çalışır ama her seferinde oluşturulan form hafızadan atılmadığı için hafıza
sürekli şişer.
Button2'nin onClick olayına yukarıdaki komutları yazdıktan sonra programı çalıştırmak
istediğinizde aşağıdaki gibi bir mesaj görüntüye gelir. Bu mesajın tam karşılığı sudur. "
Form1 formu Unit2 içinde tanımlanmış olan Form2'ye gönderme yapıyor fakat bu sizin USES
listenizde yok. Eklemek ister misiniz ? "  bu soruya Yes cevabını verdiğinizde Unit1'in uses
listesine Unit2 eklenir. Tekrar çalıştırdığınızda ise program çalışır.
Şimdi Form3'ü görüntüleyelim. Ancak bu formu görüntülerken formu tıpkı bir diyalog kutusuymuş
gibi kullanalım. Bunun için Form3'e bir Label bileşeni ekleyelim ve üç tane de düğme koyalım.
Bu düğmelerin Kind özelliğini sırasıyla bkYes, bkNo ve bkCancel yapalım. Formun boyutunu
uygun bir düzeye getirdiğimizde aşağıdaki görüntü oluşur. İsterseniz her düğme için Caption
ifadesine Evet, Hayır ve Vazgeç yazabilirsiniz.
Asıl dikkat etmemiz gereken düğmelerin Kind ve ModalResult özellikleridir. Kind özelliğine
daha önceden tanımlı değerleri yerleştirdiğinizde ilgili düğme bir bitbtn bileşeni ise düğmeye
bir resim de ilave edilir. Ayrıca ModalResult değeri de düğmenin kind'iyle (kind=tür) aynı
değeri gösterecek şekilde değişir.
Bu üç düğme için kod yazmadığımız halde üç düğme de Form3 formunu kapatır. Çünkü Form3'ü
modal olarak göstereceğiz ve modal olarak gösterilen bir formda ModalResult değeri mrNone'den
farklı bir değer aldığında form kapatılır ve değer geri gönderilir. Şimdi Form1 üzerindeki
button3 için kodları yazalım.
    procedure TForm1.Button3Click(Sender: TObject);
    Var Sonuc : Integer;
    begin
{1} Form3:=TForm3.Create(Form1);
{2} Form3.Label1.Caption:='Bu bilgi Form1den geldi';
{3} Sonuc:=Form3.ShowModal;
{4} Case Sonuc of
{5}   mrYes    : ShowMEssage('Pencere Yes düğmesi ile kapandı');
{6}   mrNo     : ShowMEssage('Pencere No düğmesi ile kapandı');
{7}   mrCancel : ShowMEssage('Pencere Cancel düğmesi ile kapandı');
{8}  End;
{9} Form3.Free;
    end;
Birinci satırda form3 form1 tarafından yaratılıyor. ( gösterime hazır hale geliyor). İkinci
satırda Form3'te yar alan Label1'e bir bilgi atanıyor. Üçüncü satırda form3 modal olarak
görüntüleniyor ve formun kapandığında gönderdiği ModalResult değeri sonuc degişkenine
aktarılıyor. 4,5,6,7 ve 8 numaralı satırlarda Sonuc içine gelen değer kontrol edilip
pencerenin kapanış şekli görüntüleniyor ve dokuzuncu satırda form3 hafızadan atılıyor.
Not : Form3'ün borderstyle özelliğini bsDialog yaparsanız maksimize ve minimize düğmeleri
de ortadan kalkacaktır.
Son olarak Form4'ü görüntüleyeceğiz. Ancak Form4 içine bazı bileşenler ekledim. Form4'ün
görünümü aşağıdadır. Düğmelerin birinin Kind'ini bkOk diğerininkini de bkCancel yaptım.
Bu formu görüntüye getireceğiz ve bu formu hafızadan silmeden önce Edit1 bileşeni içerisindeki
ifadeyi Form1'e geçireceğiz.
Bu işlemi yapmak için gerekli kodu Button4'ün onClick olayına aşağıdaki gibi yazdım. Yazılan
kodu biraz incelerseniz Form4 içindeki Edit1 bileşeninin değerini Form4'ü Free ile hafızadan
atmadan hemen önce aldım.
procedure TForm1.Button4Click(Sender: TObject);
begin
Form4:=TForm4.Create(Form1);
If Form4.ShowModal = mrOk Then ShowMessage('Form4.Edit1 içeriği:'+Form4.Edit1.Text);
Form4.Free;
end;
Bu örnekte formları birbirine nasıl bağladığımızı ve değer geçişlerini nasıl yaptığımızı
öğrendik. Programın bitmiş şeklini buraya tıklayarak alabilirsiniz.
Formlarla İlgili Birkaç İpucu ve Not
ActiveControl Bileşeni
Bir formun ActiveControl bileşeni,  ilgili form aktif durumda olduğunda; form üzerinde yer
alan bileşenlerden hangisinin seçili durumda olacağını gösterir. Eğer ActiveControl'de
gösterilen bileşen bir düğme ise form üzerinde herhangi bir yerde Enter tuşuna basmakla
ActiveControl olarak belirlenmiş düğmeye basmak aynı anlama gelir.
Kod Yazarak Bir Bileşeni Aktif Hale Getirmek
Kod yazarak form üzerindeki bir bileşeni seçili duruma getirebilirsiniz. Bunun için Tform
nesnesinin SetFocus nesnesini kullanabilirsiniz. Bu komutu kayıt ekleme düğmesine bastığınızda
klavye imlecinin ilk giriş alanına konumlanmasını sağlayabilirsiniz.  Bunun için yazmanız
gereken kodun bir örneği şu şekildedir. SetFocus:=DBEdit1;
Başlık Çubuğunda Sistem Saatinin Gösterilmesi
Formunuza ait başlık çubuğunda sistem saatini görüntüye getirebilirsiniz. Bunun için
Formunuza bir Timer bileşeni ekleyin.  Bu bileşenin Interval özelliği görüntüdeki saatin
yenilenme aralığını belirler ve 1000 değeri yaklaşık olarak 1 saniyeye karşılık gelir.
Formunuzun ana Var bölümünde hdc tipinde ve dc isminde bir değişken tanımlanmalı. Bunu
unutmayın. Timer bileşeninin onTimer olayına, formunuzun ise onCreate ve onClose olayına
gerekli kodları yazıp programı çalıştırdığınızda başlık çubuğunuzun tam ortasında saniyesi
olan bir saat göreceksiniz. Unit'in komple kodu aşağıdadır.
( Kaynak : Melsoft Pufler.Doc)
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, Mask, Buttons;
type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    MaskEdit1: TMaskEdit;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
  public
  end;
var
  Form1: TForm1;
  dc:hdc;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
  dc:=getwindowdc(handle);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
releasedc(handle,dc);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var thetime: array[0..80] of char;
begin
  strpcopy(Thetime,timetostr(time));
  canvas.font.color:=clred;
  textout(dc,width div 2,5,thetime,strlen(thetime));
end;
end.
//Başlık Çubuğuna Bir Button Eklenmesi
Formunuzun başlık çubuğunda genelde üç tane düğme vardır. Bunlar kapat, Tamekran ve
önceki boyut düğmesi bulunur. Bunların hemen sol tarafına bu düğmeler gibi yeni bir
düğme eklemek için gerekli kodlar aşağıda verilmiştir.
( Kaynak : Melsoft Pufler.Doc)
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls, Mask, Buttons;
type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    MaskEdit1: TMaskEdit;
    procedure FormResize(Sender: TObject);
  private
    CaptionBtn : TRect;
    procedure DrawCaptButton;
    procedure WMNCPaint(var Msg : TWMNCPaint); message WM_NCPaint;
    procedure WMNCActivate(var Msg : TWMNCActivate); message WM_NCACTIVATE;
    procedure WMSetText(var Msg : TWMSetText); message WM_SETTEXT;
    procedure WMNCHitTest(var Msg : TWMNCHitTest); message WM_NCHITTEST;
    procedure WMNCLButtonDown(var Msg : TWMNCLButtonDown); message WM_NCLBUTTONDOWN;
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
  dc:hdc;
implementation
const
  htCaptionBtn = htSizeLast + 1;
{$R *.DFM}
procedure TForm1.DrawCaptButton;
var
  xFrame,yFrame,xSize,ySize  : Integer;
  R : TRect;
begin
  //Form eni ve boyu
  xFrame := GetSystemMetrics(SM_CXFRAME);
  yFrame := GetSystemMetrics(SM_CYFRAME);
  //Başlık butonlarının eni ve boyu
  xSize  := GetSystemMetrics(SM_CXSIZE);
  ySize  := GetSystemMetrics(SM_CYSIZE);
  //Yeni butonun yeri
  CaptionBtn := Bounds(Width - xFrame - 4*xSize + 2,yFrame + 2, xSize - 2, ySize - 4);
  //Forma ait DC 'yi kullanarak,
  //üzerine çizim yapılacak tuvali bul
  Canvas.Handle := GetWindowDC(Self.Handle);
  Canvas.Font.Name := 'Symbol';
  Canvas.Font.Color := clBlue;
  Canvas.Font.Style := [fsBold];
  Canvas.Pen.Color := clYellow;
  Canvas.Brush.Color := clBtnFace;
  try
    DrawButtonFace(Canvas, CaptionBtn, 1, bsAutoDetect, False, False, False);
    R := Bounds(Width - xFrame - 4 * xSize + 2,
                       yFrame + 3, xSize - 6, ySize - 7);
    with CaptionBtn do
      Canvas.TextRect(R, R.Left + 2, R.Top - 1, 'W');
  finally
    ReleaseDC(Self.Handle, Canvas.Handle);
    Canvas.Handle := 0;
  end;
end;
procedure TForm1.WMNCPaint(var Msg : TWMNCPaint);
begin
  inherited;
  DrawCaptButton;
end;
procedure TForm1.WMNCActivate(var Msg : TWMNCActivate);
begin
  inherited;
  DrawCaptButton;
end;
procedure TForm1.WMSetText(var Msg : TWMSetText);
begin
  inherited;
  DrawCaptButton;
end;
procedure TForm1.WMNCHitTest(var Msg : TWMNCHitTest);
begin
  inherited;
  with Msg do
    if PtInRect(CaptionBtn, Point(XPos - Left, YPos - Top)) then
      Result := htCaptionBtn;
end;
procedure TForm1.WMNCLButtonDown(var Msg : TWMNCLButtonDown);
begin
  inherited;
  if (Msg.HitTest = htCaptionBtn) then
    ShowMessage('Hoops... yeni butona bastın');
end;
procedure TForm1.FormResize(Sender: TObject);
begin
  //Başlık çubuğunun yeniden çizilmesini sağla
  Perform(WM_NCACTIVATE, Word(Active), 0);
end;
end.
Pencerenin Taşınması
Windows pencereleri, ekran üzerinde başlıklarından tutularak taşınırlar. Pencere alanından
tutularak da taşınabilmeleri için, WM_NCHITTEST mesajının yakalanıp, yordamının değiştirilmesi
gerekir. Gerekli kod aşağıda gösterilmiştir.
type
TForm1 = class(TForm)
public
  procedure WMNCHitTest(var M: TWMNCHitTest); message WM_NCHitTest;
end;
var
  Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.WMNCHitTest(var M: TWMNCHitTest);
begin
inherited;
if M.Result = htClient then M.Result := htCaption;
end;
Bir insanın gerçek zenginliği, onun bu dünyada yaptığı iyilikleridir.

Hz.Muhammed

Safirmedya

Bir insanın gerçek zenginliği, onun bu dünyada yaptığı iyilikleridir.

Hz.Muhammed