Memik Yanık - Kişisel Web Sitesi Ana Sayfa | Hakkımda | Kitap Önerileri | Fotoğraflarım | RSS RSS | İletişim

Delphi’de Api Fonksiyonlarını Deklare Edip Kullanmak


Bilindiği gibi Delphi’de API fonksiyonlarını kullanmak son derece kolaydır. Çünkü Delphi ile gelen Windows ve ShellApi gibi bir kaç Unit sayesinde Api fonksiyonlarını Delphi fonksiyonuymuş gibi kullanmak mümkün olmaktadır. Bu nedenle Delphi konulu kaynaklarda Windows'un API fonksiyonları sanki Delphi'nin kendi fonksiyonlarıymış gibi anlatılıp kullanılmaktadır.
 
Bu makalede Delphi’nin API fonksiyonlarının kullanımını kolaylaştıran Unit’lerinden yararlanmadan nasıl kullanılabileceğini GlobalMemoryStatus() fonksiyonu üzerinde anlatmayı deneyeceğim. Delphi projelerinde Windows’un GlobalMemoryStatus() fonksiyonundan yararlanıp kullanılan bilgisayarın belleği hakkında bilgi edinebilirsiniz. Bu makaleyi ilk kaleme aldığım günlerde Delphi konulu hiç bir kaynakta API fonksiyonları böyle anlatılmamıştı. Çünkü Delphi ile gelen hazır Unıt'ler dururken kimse kendisine şu soruyu sormamıştı:"Bu unit'ler olmasaydı Windows'un API fonksiyonlarını nasıl kullanırdık?". Elbette bir çok kaynakta DLL dosyalarının nasıl hazırlanıp kullanıldığı anlatılmaktadır.
 
Tahmin edebileceğiniz gibi Windows’un API fonksiyonları C dili ile yazılmıştır. Bu nedenle bu fonksiyonları Turbo Delphi projesi dahilinde kullanabilmek için Delphi’ye uyarlamak gerekmektedir. Borland programcıların API fonksiyonlarını kolay kullanabilmesini sağlamak birkaç Unit hazırlamıştır. Windows adlı Unit bunlardan birisidir. Windows.pas adlı kod dosyasında yüzlerce API fonksiyonu hakkında bilgi bulabilirsiniz. Aşağıda verdiğim satırı "Windows.pas" dosyasından aldım.
 
procedure GlobalMemoryStatus(var lpBuffer: TMemoryStatus); stdcall;
 
Verilen bu satırdan tespit edebileceğiniz gibi Windows’un GlobalMemoryStatus fonksiyonu TMemoryStatus tipinde bir parametreye sahiptir. TMemoryStatus adı verilen bu yapının orijinal halini aşağıda görebilirsiniz.
 
typedef struct _MEMORYSTATUS { 
    DWORD dwLength;       
    DWORD dwMemoryLoad; 
    DWORD dwTotalPhys;    
    DWORD dwAvailPhys;   
    DWORD dwTotalPageFile;
    DWORD dwAvailPageFile;
    DWORD dwTotalVirtual; 
    DWORD dwAvailVirtual; 
} MEMORYSTATUS, *LPMEMORYSTATUS;
 
Delphi projelerinde Windows’un GlobalMemoryStatus fonksiyonunu kullanabilmek için bu yapının Delphi’ye uyarlanması gerekiyor. Başka bir deyişle C’de Struct olarak yapılan tanımlamanın Delphi’de Record olarak yapılması gerekmektedir. Bu hazırlık Delphi ile gelen Windows.pas adlı Unit’te yapılmış olduğu için sizler GlobalMemoryStatus fonksiyonun gerek duyduğu tipi hazırlamak zorunda değilsiniz. Buradaki amacımızın deneysel olduğunu unutmamak gerekir.
 
type
 PMemoryStatus = ^TMemoryStatus;
 _MEMORYSTATUS = record
    dwLength: DWORD;
    dwMemoryLoad: DWORD;
    dwTotalPhys: DWORD;
    dwAvailPhys: DWORD;
    dwTotalPageFile: DWORD;
    dwAvailPageFile: DWORD;
    dwTotalVirtual: DWORD;
    dwAvailVirtual: DWORD;
 end;
 
Her ne kadar Windows’a ait bir fonksiyon olsa bile Delphi’nin Windows.pas adlı Unit’inde gerekli tanımlamalar yapıldığı için sanki Delphi’nin bir fonksiyonuymuş gibi kullanabileceğiniz GlobalMemoryStatus() fonksiyonu hakkında bilgi vermek için forma 3 Edit yerleştirdim. Devamında aşağıda verdiğim kodu yazdım. Windows adlı Unit veya Windows.pas dosyası formları temsil eden Unit’lere otomatik olarak dahil edildiği için Uses bloğu ile ilgilenmenize gerek yoktur.
 
procedure TForm1.Bellek_durumuClick(Sender: TObject);
Var
  Bellek : TMEMORYSTATUS;
begin
  GlobalMemoryStatus(Bellek);
  Edit1.Text := IntToStr(Bellek.dwTotalPhys div 1024 div 1024) +' MB';
  Edit2.Text := '%' + IntToStr(Bellek.dwMemoryLoad);
  Edit3.Text := IntToStr(Bellek.dwAvailPhys Div 1024 Div 1024) +' MB';
end;
 
Bu kodu incelediğinizde önce TMEMORYSTATUS tipinde bir değişkenin tanımlanıp bu değişkenin GlobalMemoryStatus() fonksiyonuna parametre olarak verildiğini, devamında ise bu tipin elamanlarından 3 tanesinin içeriğinin Edit’lere aktarıldığını görürsünüz. Tabi burada "Bellek" adında değişken tanımlamış olmakla kendimi tehlikeye atmış oluyorum. Yarın bir gün yerli programcılık kitabı yazarının Bellek'i değişken adı olarak kullanmanın patentini almış olabilir(!).
 
GlobalMemoryStatus fonksiyonu hakkında şimdiye kadar anlatılanlara göre konu Windows’un API fonksiyonları olduğunda bu fonksiyonları kullanmak son derece kolaydır. Çünkü Windows’un çok sayıda fonksiyonu için "Windows.pas" ve "ShellApi.pas" gibi Delphi’ye ait Unit’lerde gereken hazırlıklar önceden yapılmıştır.
 
Şimdi Windows.pas adlı Unit’i Delphi projesine dahil etmeden GlobalMemoryStatus fonksiyonundan yararlanıp bilgisayarın belleği hakkında bilgi edineceğim. Bu amaçla üzerinde çalıştığım projenin ilk formunun tanımlandığı yani ilk formu temsil eden Class'ın hazırlandığı Unit’in Uses bloğundan Windows adlı Unit’i sildim ve TBELLEK_DURUMU adında bir tip tanımladım.
 
unit Unit1;
interface
uses
  Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, Menus;
Type
  TBELLEK_DURUMU = record
     dwLength: LONGINT;
     dwMemoryLoad: LONGINT;
     dwTotalPhys: LONGINT;
     dwAvailPhys: LONGINT;
     dwTotalPageFile: LONGINT;
     dwAvailPageFile: LONGINT;
     dwTotalVirtual: LONGINT;
     dwAvailVirtual: LONGINT;
  end;
type
  TForm1 = class(TForm)
     procedure FormClick(Sender: TObject);
  private
  public
  end;
var
  Form1: TForm1;
 
Bu tipi tanımlarken yukarıda verdiğim Windows’a ait orijinal Struct veya yapıdan yararlandım. Üzerinde çalıştığım projenin ilk formunu temsil eden bu Unit’in Uses bloğunu incelerseniz Windows adlı hazır Unit’in olmadığını görürsünüz. Windows’un GlobalMemoryStatus adlı API fonksiyonun gerek duyduğu tipi bu şekilde tanımladıktan sonra formu temsil eden Unit’in implementation bölümde bu API fonksiyonunu aşağıdaki gibi deklare ettim.
 
implementation
Function GlobalMemoryStatus(Var Bellek : TBELLEK_DURUMU): Integer;
         StdCall; External 'Kernel32.dll';
{$R *.dfm}
 
Bu fonksiyon Microsoft tarafından hazırlanırken StdCall yöntemi ile çağrılması konusunda ayarlama yapıldığı için fonksiyonun yapısına StdCall anahtar kelimesini ekledim. Devamında External anahtar kelimesi ile fonksiyonun tanımlı olduğu DLL dosyasını işaret ettim.
 
Fonksiyonu deklare ederken fonksiyonun gerek duyduğu parametrenin yukarıda kendi tanımladığım tipte(TBELLEK_DURUMU) olmasını sağladım. Her ne kadar bu fonksiyonun dönüş değeri Integer tipinde olsa bile geriye gönderilen bilgiyi yakalamak zorunda değilsiniz. Bu hazırlıktan sonra bu fonksiyonu aşağıdaki gibi kullandım.
 
procedure TForm1.Bellek_durumuClick(Sender: TObject);
Var
  Bellek : TBELLEK_DURUMU;
begin
  GlobalMemoryStatus(Bellek);
  Edit1.Text := IntToStr(Bellek.dwTotalPhys div 1024 div 1024) + ' MB';
  Edit2.Text := '%' + IntToStr(Bellek.dwMemoryLoad);
  Edit3.Text := IntToStr(Bellek.dwAvailPhys Div 1024 Div 1024) + ' MB';
end;
 
Şimdi ise Windows’un orijinali GlobalMemoryStatus olan adını kullanmak yerine fonksiyona takma bir isim vereceğim. Fonksiyonlara takma isim verme işlemi Unit’lerin implementation bölgesinde fonksiyon deklare edilirken verilir.
 
implementation
Function Bellek_bilgisi(var Bellek :TBELLEK_DURUMU): Integer;
      StdCall; external 'kernel32.dll' Name 'GlobalMemoryStatus';
{$R *.dfm}
procedure TForm1.Bellek_durumuClick(Sender: TObject);
Var
   Bellek : TBELLEK_DURUMU;
begin
   Bellek_bilgisi(Bellek);
   Edit1.Text := IntToStr(Bellek.dwTotalPhys div 1024 div 1024) + ' MB';
   Edit2.Text := '%' + IntToStr(Bellek.dwMemoryLoad);
   Edit3.Text := IntToStr(Bellek.dwAvailPhys Div 1024 Div 1024) + ' MB';
end;
 
Burada Name anahtar kelimesinden sonra yazılan ad, işaret edilen DLL dosyasındaki fonksiyonun gerçek adıdır. Bu tanımlamadan sonra Windows’un GlobalMemoryStatus adlı API fonksiyonu Delphi projesi dahilinde Bellek_bilgisi() adıyla çağrılabilir. GlobalMemoryStatus fonksiyonunda yapıldığı gibi diğer API fonksiyonların hem Delphi’den yardım alarak hem almayarak nasıl kullanıldığı uzun uzun anlatılabilir ancak buna gerek yoktur.

Delphi 13.05.2009 23:24:32

YORUM YOK


YorumlarYorum Yaz
Ana Sayfa | Hakkımda | Kitap Önerileri | Fotoğraflarım | RSS | İletişim
Memik Yanık 2004-2009 © Tüm Hakları Saklıdır.
Hazırlayan www.semgoksu.com