Delphi ile "Login olmak" (Kullanıcı giriş denetimi)
- 20 Mayıs 2010 Perşembe
- Uğur Parlayan
Yazılara uzun bir süre ara verdikten sonra aşağıdaki gibi bir örnekle geri
dönmek sanırım hepimiz için güzel bir başlangıç olacak...
Yazdığımız programlarda kullanıcının programa girişini kontrol altına almak,
yetkileri ve arabirimi kullanıcıya göre giriş esnasında şekillendirmek
herzaman bizler için bir sıkıntı olmuştur. Bu yazıda bu sorunu nasıl
aşabileceğimize dair hazırladığım özel bir bileşeni tanıtacağım;
TupLoginDialog...
TupLogindialog Ne İşe Yarar
Bu bileşen, programcının tercihine bağlı kalarak açılış anında veya bir
butonun tetiklemesiyle devreye girip kullanıcıdan kullanıcı adı ve şifresini
bir forma girmesini, girdiği bilgileri kullanarak o kullanıcının
veritabanından kontrol edilmesini, varsa programa girmesine izin vermesini,
yoksa kullanıcıyı uyarmasını, belli bir miktar hatalı girişten sonra programı
kapatmasını sağlayan nevişahsına münhasır özel bir bileşenimizdir.
Tasarım anında görsel olmayan bir nesne olarak kullanılır. Sizden, ana
formunuza bu bileşeni eklediğinizde aşağıdaki alanları doldurmanızı ister.
Temel parametreleri girdiğinizde çalıştırılmaya hazırdır. Ayrıca sonuca göre 2
farklı olay da tetikleyebilmektedir. 1. Olayda, kullanıcı adı ve şifresi
doğrulanan bir kullanıcı veritabanında bulunduysa OnGirisKabulEdildi olayını
tetikler. Eğer belirttiğiniz miktarda hatalı bir giriş denemesi yapıldıysa
limit dolduğunda OnHataLimiti olayını tetikler. Bu olaylar size giriş
düğmesine basıldığında programınızda kullanıcı ile ilgili diğer işlemleri
yapmanıza, belli miktarda hatalı giriş yapıldığında ise programınızı
kapatmadan önce yapmanız gereken diğer işlemleri gerçekleştirmenize veya
ilgili kullanıcının hesabını kilitlemenize olanak verir.
TupLoginDialog Bileşeninin Kaynak Kodu
Aşağıda, size bu bileşenin kaynak kodunu veriyorum. Bu bileşen ile ilgili
teknik detayları ayrı ayrı da anlatabilirdim fakat konu bütünlüğünün
bozulmaması için gereken açıklamaları kodun içine serpiştirdim, neyi neden ve
nerede yaptığımı böylece daha iyi anlatabileceğimi düşünüyorum...
{******************************************************************************}
{* *}
{* Programlayan: Uğur Parlayan (ugurparlayan@gmail.com) *}
{* Tarih: 17.05.2010 *}
{* *}
{* Kullanım: Ayrım gözetmeksizn külliyatıyla ÜCRETSİZDİR *}
{* Yazarın gönlü olsun diye kaynak belirtirseniz sevinirim... *}
{* *}
{* Uygulamanıza Kullanıcı adı ve şifre ile giriş yapılabilmesine imkân verir *}
{* *}
{* URL: http://www.kavramca.com/index.php?k=40 *}
{* *}
{******************************************************************************}
unit upLoginDialog;
interface
uses
SysUtils, Classes, StdCtrls, Mask, DBCtrls, DB, ExtCtrls, Controls, Buttons,
Variants, Messages, Windows, Forms, Dialogs, ADODB, Grids, DBGrids, Graphics,
AppEvnts;
const
WM_AFTER_SHOW = WM_USER + 300;
WM_AFTER_CREATE = WM_USER + 301;
type
TupLoginDialog = class(TCommonDialog)
private
FUygulamaOlayi : TApplicationEvents;
{Pencerenin iç nesneleri}
FPencere : TForm;
FCMB_Kullanici : TComboBox;
FEdit_Sifre : TEdit;
FBTN_Giris : TButton;
FBTN_Kapat : TButton;
FLBL_Kullanici : TLabel;
FLBL_Sifre : TLabel;
FBTN_Hatirlatici : TButton;
{Diğer zımbırtılar}
FConnection : TAdoConnection;
FGirisKabulEdildi : TNotifyEvent; {Girişte tetiklenen olay.}
FHataLimiti : TNotifyEvent;
FOtomatikBaslat : Boolean; {Program çalışınca devreye girecek mi}
FGirebilir : Boolean; {Giriş izni verildi mi}
FKullaniciListele : Boolean;
FKullanici_Tablosu : string;
FHatirlatmaGoster : Boolean;
FAlan_Soru : string;
FAlan_Cevap : string;
FAlan_Key : string;
FAlan_Kullanici : string;
FAlan_Sifre : string;
FAlan_Pasif : string;
FAlan_SonTarih : string;
FAlan_Yetkiler : string;
FAlan_Hesap : string;
FMetin_Baslik : string;
FMetin_Kullanici : string;
FMetin_Sifre : string;
FMetin_Login : string;
FMetin_Kapat : string;
FMetin_Hatirlat : string;
FValue_Kullanci : string;
FValue_Sifre : string;
FValue_Hesap : string;
FValue_Key : string;
FValue_Yetkiler : string;
FValue_Pasif : Boolean;
FHataSayaciKullan : Boolean;
FHataSayaci : Integer;
function GetSQL : string;
function GetBilesenDurumu: string;
function GetValue_Kullanci: string;
function GetValue_Sifre: string;
procedure SetConnection(const Value: TAdoConnection);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormShow(Sender: TObject);
{Ana programa sistem mesajı gönderir...}
procedure OnMsg(var Msg:tagMsg;var Handled:Boolean);
procedure Klik_Tus(Sender: TObject; var Key: Char);
procedure Klik_Giris(Sender: TObject);
procedure Klik_Kapat(Sender: TObject);
procedure Klik_Hatirlat(Sender: TObject);
procedure Sifirla;{Pencere açılmadan önce sonuçları sıfırlar...}
procedure Sonuclar;
procedure Olustur;{Penceremizi oluşturur...}
property OnClose;
property OnShow;
protected
procedure DoGirisKabulEdildi; virtual;
procedure DoHataLimiti; virtual;
public
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
procedure Calistir;{Dialog penceresini istenilen esnada gösterir}
published
property Connection : TAdoConnection read FConnection
write SetConnection;
{SQL cümlemizi parametrelere göre üretir.}
property SQL : string read GetSQL;
{Bileşen için gereken kritik değişkenler hakkında dış ortama bilgi verir.}
property BilesenDurumu : string read GetBilesenDurumu;
{Kaç kere hata yapılabileceğini bu değişken karar verir}
property HataSayaci : Integer read FHataSayaci
write FHataSayaci
Default 10;
{Eğer istersek kullanıcının hatalarını saymayabiliriz...}
property HataSayaciKullan : Boolean read FHataSayaciKullan
write FHataSayaciKullan
Default False;
{Şifresini unutan kullanıcıya soru sorabiliriz}
property HatirlatmaGoster : Boolean read FHatirlatmaGoster
write FHatirlatmaGoster
Default False;
{Ana form çalışır çalışmaz devreye girmesini sağlayabiliriz.}
property OtomatikBaslat : Boolean read FOtomatikBaslat
write FOtomatikBaslat
Default False;
{Kullanıcı adlarını eğer istersek listeleyebiliriz, ŞART DEĞİL !!!}
property Kullanici_Listele : Boolean read FKullaniciListele
write FKullaniciListele
Default False;
{Temel Parametre: Kullanıcıların veritabanındaki tablo adı}
property Kullanici_Tablosu : string read FKullanici_Tablosu
write FKullanici_Tablosu;
{Temel Parametre: USERNAME alanı}
property Alan_Kullanici : string read FAlan_Kullanici
write FAlan_Kullanici;
{Temel Parametre: PASSWORD alanı}
property Alan_Sifre : string read FAlan_Sifre
write FAlan_Sifre;
{Şart değil: Sorunun tutulduğu tablo alanı}
property Alan_Soru : string read FAlan_Soru
write FAlan_Soru;
{Şart değil: Cevabın tutlduğu tablo alanı}
property Alan_Cevap : string read FAlan_Cevap
write FAlan_Cevap;
{Temel Parametre: Her kullanıcı için bir referans numarası vardır}
{Bu alan işte o referansı kullanmanızı sağlar (PRIMARY KEY)}
property Alan_Key : string read FAlan_Key
write FAlan_Key;
{Şart değil: Pasifleştirilmiş kullanıcıları sonuçlardan dışlar...}
property Alan_Pasif : string read FAlan_Pasif
write FAlan_Pasif;
{Şart değil: Eğer kullanıcının belli bir tarihten sonra giriş }
{yapmasını istemiyorsanız bunu kullanabilirsiniz...}
property Alan_SonTarih : string read FAlan_SonTarih
write FAlan_SonTarih;
{Şart değil: Giriş yaptıktan sonra yetkileri denetlemenizi sağlar}
property Alan_Yetkiler : string read FAlan_Yetkiler
write FAlan_Yetkiler;
{Şart değil: ACCOUNT alanı...}
property Alan_Hesap : string read FAlan_Hesap
write FAlan_Hesap;
{Görsel: Pencerenin başlığı}
property Metin_Baslik : string read FMetin_Baslik
write FMetin_Baslik;
{Görsel: Giriş düğmesinin başlığı}
property Metin_Login : string read FMetin_Login
write FMetin_Login;
{Görsel: Kapat düğmesinin başlığı}
property Metin_Kapat : string read FMetin_Kapat
write FMetin_Kapat;
{Görsel: Kullanıcı adı text alanının başlığı}
property Metin_Kullanici : string read FMetin_Kullanici
write FMetin_Kullanici;
{Görsel: Şifre text alanının başlığı}
property Metin_Sifre : string read FMetin_Sifre
write FMetin_Sifre;
{Görsel: "Şifremi Unuttum" düğmesinin başlığı}
property Metin_Hatirlat : string read FMetin_Hatirlat
write FMetin_Hatirlat;
{SONUÇ: Kullanıcı adı}
property Value_Kullanici : string read GetValue_Kullanci
write FValue_Kullanci;
{SONUÇ: Şifresi}
property Value_Sifre : string read GetValue_Sifre
write FValue_Sifre;
{SONUÇ: PRIMARY KEY}
property Value_Key : string read FValue_Key;
{SONUÇ: Bu kullanıcının yetkileri}
property Value_Yetkiler : string read FValue_Yetkiler;
{SONUÇ: ACCOUNT adı...}
property Value_Hesap : string read FValue_Hesap;
{SONUÇ: Aktif / Pasif kullanıcı olup olmadığı...}
property Value_Pasif : Boolean read FValue_Pasif;
{SONUÇ: Kullanıcının mevcut olup olmadığının kararı...}
property Girebilir : Boolean read FGirebilir
Default False;
{OLAY: Giriş düğmesi olayı}
property GirisKabulEdildi : TNotifyEvent read FGirisKabulEdildi
write FGirisKabulEdildi;
{OlAY: Hata sayacı olayı}
property HataLimiti : TNotifyEvent read FHataLimiti
write FHataLimiti;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('UgurPack2007', [TupLoginDialog]);
end;
{ TupLoginDialog }
constructor TupLoginDialog.Create(AOwner: TComponent);
begin
inherited;
{ Varsayılanları ayarlıyoruz... }
if (FMetin_Baslik = '') then FMetin_Baslik := 'Kullanıcı Girişi';
if (FMetin_Kapat = '') then FMetin_Kapat := 'Kapat';
if (FMetin_Login = '') then FMetin_Login := 'Giriş';
if (FMetin_Kullanici = '') then FMetin_Kullanici := 'Kullanıcı Adı :';
if (FMetin_Sifre = '') then FMetin_Sifre := 'Şifre :';
if (FMetin_Hatirlat = '') then FMetin_Hatirlat := 'Şifremi Unuttum';
FHataSayaci := 10; {Kullansak da kullanmasak da bu varsayılan miktardır...}
{ Uygulama olayı tanımlıyoruz, Başlangıçta devreye girebilsin diye... }
FUygulamaOlayi := TApplicationEvents.Create(Self);
FUygulamaOlayi.OnMessage := OnMsg;
PostMessage(TForm(Owner).Handle, WM_AFTER_CREATE, 0, 0);
end;
destructor TupLoginDialog.Destroy;
begin
FUygulamaOlayi.Destroy;
inherited;
end;
procedure TupLoginDialog.DoGirisKabulEdildi;
begin
{ Giriş düğmesine bsama olayını burada atama yapıyoruz }
if Assigned(FGirisKabulEdildi) then FGirisKabulEdildi(SELF);
end;
procedure TupLoginDialog.DoHataLimiti;
begin
{ Hata miktarının tetiklenmesi olayını burada atama yapıyoruz }
if Assigned(FHataLimiti) then FHataLimiti(SELF);
end;
procedure TupLoginDialog.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{ Form kapatıldığında onu yoketmeyip sadece gizliyoruz. }
Action := caHide;
{ caFREE kullansaydık nesneyi yoketmiş olurduk ki bu da hata üretir... }
if (FGirebilir = False) then begin
MessageBox(TForm(Owner).Handle, 'Program Kapatılacaktır.',
PWideChar(Application.Title), MB_OK + MB_ICONERROR);
PostMessage(TForm(Owner).Handle, WM_CLOSE, 0, 0);
{ Şifreyi giremediyse ana programı da kapat...}
end;
end;
procedure TupLoginDialog.FormShow(Sender: TObject);
var
FADS: TAdoDataSet;
SQL: String;
I: Integer;
Sonuc: String;
Ek: String;
begin
{ Formu çalıştırdığımızda bu kısım devreye giriyor }
{ Nesnelerimiz mevcutsa önce imleci kullanıcı adı text alanına }
{ konumlandırıyor, sonra da eğer kullanıcı listesi göstereceksek değerleri }
{ okuyup ilgili bileşene yazıyor... }
if Assigned(FPencere) and Assigned(FCMB_Kullanici) then begin
FCMB_Kullanici.SetFocus;
if (FAlan_Kullanici>'')
and (FKullanici_Tablosu>'')
and (FKullaniciListele = True)
then begin
SQL := '';
SQL := FORMAT('SELECT DISTINCT [%s] FROM dbo.[%s]',
[FAlan_Kullanici, FKullanici_Tablosu]);
if (FAlan_Pasif>'') or (FAlan_SonTarih>'') then begin
SQL := FORMAT('%s WHERE', [SQL]);
if (FAlan_Pasif > '') then SQL := FORMAT('%s ISNULL([%s],0) =
0', [SQL, Alan_Pasif]);
if (FAlan_Pasif>'') and (FAlan_SonTarih>'') then SQL :=
FORMAT('%s AND',[SQL]);
if (FAlan_SonTarih>'') then SQL := FORMAT('%s ISNULL([%s],0) <=
GETDATE()', [SQL, Alan_SonTarih]);
end;
if (SQL > '') then begin
FADS := TADODataSet.Create(Application);
with FADS do begin
Close;
Connection := FConnection;
CommandType := cmdText;
CommandText := SQL;
Open;
First;
end;
if (FADS.IsEmpty = False) then begin
for I := 0 to FADS.RecordCount - 1 do begin
Sonuc := Sonuc +
FORMAT('"%s",',[FADS.FieldByName(FAlan_Kullanici).AsString]);
FADS.Next;
end;
with FCMB_Kullanici.Items do begin
QuoteChar := '"';
Delimiter := ',';
DelimitedText := Sonuc;
end;
end;
FADS.Close;
FADS.Destroy;
end;
end else begin
FCMB_Kullanici.Style := csSimple;
end;
end;
end;
function TupLoginDialog.GetSQL: string;
var
SQL_Cumlesi: String;
begin
{ Kullanıcı adı, şifre, tablo, varsa pasif ve varsa son tarihle birlikte }
{ bu bilgilerini kullanarak bir SQL cümlesi üretiyor}
SQL_Cumlesi := '';
SQL_Cumlesi := FORMAT('SELECT TOP 1 [%s]',[FAlan_Key]);
if (FAlan_Hesap>'') then SQL_Cumlesi := FORMAT('%s, [%s]',[SQL_Cumlesi,
FAlan_Hesap]);
if (FAlan_Yetkiler>'') then SQL_Cumlesi := FORMAT('%s, [%s]',[SQL_Cumlesi,
FAlan_Yetkiler]);
SQL_Cumlesi := FORMAT('%s FROM dbo.[%s] WHERE [%s]=''%s'' AND [%s]=''%s''',
[ SQL_Cumlesi
, FKullanici_Tablosu
, Alan_Kullanici
, GetValue_Kullanci
, Alan_Sifre
, GetValue_Sifre
]);
if (Alan_Pasif > '') then SQL_Cumlesi := FORMAT('%s AND ISNULL([%s],0) =
0', [SQL_Cumlesi, Alan_Pasif]);
if (FAlan_SonTarih>'') then SQL_Cumlesi := FORMAT('%s AND ISNULL([%s],0) <=
GETDATE()', [SQL_Cumlesi, Alan_SonTarih]);
Result := SQL_Cumlesi;
end;
function TupLoginDialog.GetBilesenDurumu: string;
var
Sonuc: String;
begin
{ Bu bileşen için gerekli olan kritik değişkenler hakkında dış ortama bilgi
verir. }
Sonuc := '';
if NOT Assigned(FConnection) then Sonuc := Sonuc + 'Bağlantı nesnesi eksik.
';
if Assigned(FConnection) then begin
if (FConnection.Connected = False) then Sonuc := Sonuc + 'Bağlantı
nesnesi KAPALI ! ';
end;
if (FAlan_Key = '') then Sonuc := Sonuc + 'Anahtar alan
belirtilmemiş. ';
if (FAlan_Kullanici = '') then Sonuc := Sonuc + 'Kullanıcı adı alanı
belirtilmemiş. ';
if (FAlan_Sifre = '') then Sonuc := Sonuc + 'Şifre alanı
belirtilmemiş. ';
if (FKullanici_Tablosu = '') then Sonuc := Sonuc + 'Kullanıcı tablosu
belirtilmemiş. ';
if (Sonuc = '') then Sonuc := 'Temel parametreler mükemmel';
Result := Sonuc;
end;
function TupLoginDialog.GetValue_Kullanci: string;
begin
{ girişten sonra dış ortama kullanıcı adını veriyor... }
if Assigned(FCMB_Kullanici)
then Result := FCMB_Kullanici.Text
else Result := FValue_Kullanci;
end;
function TupLoginDialog.GetValue_Sifre: string;
begin
{ girişten sonra dış ortama şifreyi veriyor... }
{ Tabii ki dış ortamdan kastım sadece "ana form"... }
if (Assigned(FEdit_Sifre) = True)
then Result := FEdit_Sifre.Text
else Result := FValue_Sifre;
end;
procedure TupLoginDialog.Calistir;
begin
{ Siz, ana formda "Kullanıcı Girişi" diye bir butondan bunu çağırırsanız }
{ önce oluşturulmamışsa giriş formunu üretir, sonra sonuçları sıfırlar }
{ en sonunda da giriş formunu gösterir... }
if NOT Assigned(FPencere)
then Olustur;
Sifirla;
FPencere.ShowModal;
end;
procedure TupLoginDialog.Klik_Kapat(Sender: TObject);
begin
{ Kapat düğmesine bastığımızda bu işlem gerçekleşir... }
Fpencere.Close;
end;
procedure TupLoginDialog.Klik_Giris(Sender: TObject);
begin
{ Giriş düğmesine bastığımızda burası devreye girer; Kısaca şu işleri yapar }
{ Kullanıcının kullanıcı adı ve parametresini veritabanından sorgular }
{ Sonuçta bu kişi girebiliyorsa ana forma geçiş yapar}
{ giremiyorsa uygun bir dille uyarır... }
{ Hatta hata sayacı da burada sayılır ve kontrol edilir...}
Sonuclar;
if (FGirebilir = True) then Begin
GirisKabulEdildi(SELF);
FPencere.Close;
End else Begin
if (FHataSayaciKullan = True) then Begin
FHataSayaci := FHataSayaci - 1;
if (FHataSayaci <= 0) then begin
FGirebilir := False;
if Assigned(FHataLimiti) then HataLimiti(SELF);
FPencere.Close;
//Exit;
end else begin
MessageBox(TForm(Owner).Handle,PWideChar('Hatalı giriş yaptınız.
'+IntToSTR(FHataSayaci)+' defa daha hatalı giriş yaparsanız program
kapanacaktır. '#13#10'Lütfen sistem yöneticinize
danışınız...'),'HATA',MB_OK+MB_ICONERROR);
end;
End else Begin
MessageBox(TForm(Owner).Handle,'Kullanıcı adı ve/ya Şifreniz yok
ve/ya yanlış.'#13#10'Lütfen sistem yöneticinize
danışınız...','HATA',MB_OK+MB_ICONERROR);
end;
end;
end;
procedure TupLoginDialog.Klik_Hatirlat(Sender: TObject);
var
Soru : String;
Cevap: String;
Yanit: String;
Sifre: String;
FADS : TAdoDataSet;
begin
{ Eğer kullanıcımız, sevgili şifresini unuttuysa ona bir soru sormamız }
{ gerekir. Verdiği cevap ile veritabanındaki yanıt aynı ise ona şifresini }
{ gösteririz, yanlış bir yanıt verdiyse hata mesajı üretiriz...}
{ Tüm bunları yapabilmek için kullanıcı adının yazılmış olması gerekir... }
if (FHatirlatmaGoster = True) and (FAlan_Soru > '') and (FAlan_Cevap > '')
then begin
if (FCMB_Kullanici.Text > '') then begin
FADS := TADODataSet.Create(Application);
with FADS do begin
Close;
Connection := FConnection;
CommandType := cmdText;
CommandText := FORMAT('SELECT TOP 1 * FROM dbo.[%s] WHERE [%s]
= ''%s''', [FKullanici_Tablosu, FAlan_Kullanici, FCMB_Kullanici.Text]);
Open;
Soru := FieldByName(FAlan_Soru).AsString;
Cevap:= FieldByName(FAlan_Cevap).AsString;
Sifre:= FieldByName(FAlan_Sifre).AsString;
Close;
end;
FADS.Free;
Yanit := InputBox('Lütfen soruyu cevaplayın', Soru, '');
if lowercase(Yanit) = lowercase(Cevap) then ShowMessage(Sifre)
else MessageBox(TForm(Owner).Handle,'Yanlış
yanıt.','HATA',MB_OK+MB_ICONWARNING);
end else begin
MessageBox(TForm(Owner).Handle,'Lütfen Kullanıcı Adınızı
yazınız.','HATA',MB_OK+MB_ICONWARNING);
end;
end;
end;
procedure TupLoginDialog.Olustur;
const
sbt_Aralik = 4; { Penceredeki düğmeler arasındaki boşluk (Pixel
cinsinden...)}
sbt_Padding = 10;
sbt_ButonGenislik = 75;
sbt_ButonYukseklik = 25;
begin
{Dialog penceresini tüm unsurlarıyla birlikte üretir.}
if NOT Assigned (FPencere) then
FPencere := TForm.Create(Application.Owner);
with FPencere do begin
Position := poMainFormCenter;
KeyPreview := True;
Caption := Metin_Baslik;
ShowHint := True;
Width := 350;
Height := 130;
BorderStyle := bsDialog;
FormStyle := fsStayOnTop;
OnClose := FormClose;
OnShow := FormShow;
//OnPaint := PencereBoyutlandir;
//OnKeyDown := FormKeyDown; {Özel bir tuşa basılırsa...}
{ OnResize := PencereBoyutlandir; Bunu kullanmıyoruz, }
{ Çünkü nesne henüz "üretim" aşamasında olduğu için OnResize }
{ olayı anında devreye giriyor ve hata üretiyor. Bunu önlemek için }
{ bu kısma bir değer atamıyoruz. Belki OnPaint olayına tanımlanabilir. }
{ Show; Bunu özellikle çalıştırmadık... }
end;
if NOT Assigned (FLBL_Kullanici) then
FLBL_Kullanici := TLabel.Create(FPencere);
with FLBL_Kullanici do begin
Parent := FPencere;
Left := sbt_Padding;
Top := sbt_Padding + sbt_Aralik;
Height := 17;
Caption := Metin_Kullanici;
AutoSize := True; {Kendi genişliğini kendisi ayarlasın...}
Show;
end;
if NOT Assigned (FCMB_Kullanici) then
FCMB_Kullanici := TComboBox.Create(FPencere);
with FCMB_Kullanici do begin
Parent := FPencere;
Height := 20;
Top := sbt_Padding;
Left := FLBL_Kullanici.Left + FLBL_Kullanici.Width +
sbt_Aralik;
Width := FPencere.ClientWidth
- Left
- sbt_Padding;
if (FValue_Kullanci>'') then Text := FValue_Kullanci
else Text := '';
OnKeyPress := Klik_Tus;
Anchors := [akLeft,akTop,akRight]; { Pencere boyu değiştiğinde
uyum sağlasın }
Text := FValue_Kullanci;
Show;
end;
if NOT Assigned (FLBL_Sifre) then
FLBL_Sifre := TLabel.Create(FPencere);
with FLBL_Sifre do begin
Parent := FPencere;
Left := sbt_Padding;
Top := FCMB_Kullanici.Top +
FCMB_Kullanici.Height+sbt_Aralik+2;
Height := 17;
Caption := Metin_Sifre;
AutoSize := True; {Kendi genişliğini kendisi ayarlasın...}
Show;
end;
if NOT Assigned (FEdit_Sifre) then
FEdit_Sifre := TEdit.Create(FPencere);
with FEdit_Sifre do begin
Parent := FPencere;
Height := 20;
{şifremizi yazarken tepemizdekiler ne yazdığımız görmesin...}
PasswordChar := '?';
Top := FCMB_Kullanici.Top + FCMB_Kullanici.Height +
sbt_Aralik;
Left := FLBL_Kullanici.Left + FLBL_Kullanici.Width +
sbt_Aralik;
Width := FPencere.ClientWidth
- Left
- sbt_Padding;
if (FValue_Kullanci > '') then Text := FValue_Kullanci
else Text := '';
OnKeyPress := Klik_Tus;
Anchors := [akLeft,akTop,akRight]; { Pencere boyu değiştiğinde
uyum sağlasın }
Text := FValue_Sifre;
Show;
end;
if NOT Assigned (FBTN_Giris) then
FBTN_Giris := TButton.Create(FPencere);
with FBTN_Giris do begin
Caption := FMetin_Login;
Anchors := [akRight,akTop];
Parent := FPencere;
Width :=
TForm(Owner).Canvas.TextWidth(FMetin_Login)+(sbt_Padding*2); // 40
Height := sbt_ButonYukseklik;
Top := FEdit_Sifre.Top + FEdit_Sifre.Height + sbt_Aralik +
sbt_Padding;
Left := FPencere.ClientWidth - sbt_Padding - width;
OnClick := Klik_Giris;
Show;
end;
if NOT Assigned (FBTN_Kapat) then
FBTN_Kapat := TButton.Create(FPencere);
with FBTN_Kapat do begin
Caption := FMetin_Kapat;
Anchors := [akRight,akTop];
Parent := FPencere;
Width :=
TForm(Owner).Canvas.TextWidth(FMetin_Kapat)+(sbt_Padding*2);
Height := sbt_ButonYukseklik;
Top := FEdit_Sifre.Top + FEdit_Sifre.Height + sbt_Aralik +
sbt_Padding;
Left := FBTN_Giris.Left - sbt_Aralik - width;
OnClick := Klik_Kapat;
Show;
end;
if NOT Assigned(FBTN_Hatirlatici) then
FBTN_Hatirlatici:= TButton.Create(FPencere);
with FBTN_Hatirlatici do begin
Caption := FMetin_Hatirlat;
Anchors := [akLeft,akTop];
Parent := FPencere;
Width :=
TForm(Owner).Canvas.TextWidth(FMetin_Hatirlat)+sbt_Padding;
Height := sbt_ButonYukseklik;
Top := FEdit_Sifre.Top + FEdit_Sifre.Height + sbt_Aralik +
sbt_Padding;
Left := sbt_Padding;
OnClick := Klik_Hatirlat;
if (FHatirlatmaGoster = True) then Show else Hide;
end;
end;
procedure TupLoginDialog.OnMsg(var Msg: tagMsg; var Handled: Boolean);
begin
{ Ana forma burası aracılığıyla mesaj gönderiyoruz... }
case Msg.message of
WM_AFTER_SHOW:
begin
if (GetBilesenDurumu = 'Temel parametreler mükemmel') then begin
if not Assigned(FPencere) then Olustur;
Calistir;
end else begin
MessageBox(TForm(Owner).Handle,'Parametreler eksik veya yanlış
olabilir. Lütfen kontrol ediniz..','HATA',MB_OK+MB_ICONSTOP);
end;
end;
WM_AFTER_CREATE:
begin
if NOT (csDesigning in ComponentState) then
if (FOtomatikBaslat = True)
then PostMessage(TForm(Owner).Handle, WM_AFTER_SHOW, 0, 0);
end;
end;
end;
procedure TupLoginDialog.SetConnection(const Value: TAdoConnection);
begin
{ Malesef ADO (dbGO) bileşenlerini destekleyebiliyoruz. }
FConnection := Value;
end;
procedure TupLoginDialog.Sifirla;
begin
{ Anladınız siz bunu... }
FValue_Key := '';
FValue_Hesap := '';
FValue_Yetkiler:= '';
FValue_Kullanci:= '';
FValue_Sifre := '';
FValue_Pasif := FALSE;
end;
procedure TupLoginDialog.Sonuclar;
var
FADS: TAdoDataSet;
begin
{ Eğer temel parametrelerimizde herhangi bir pürüz yoksa sonuç alabiliriz...}
try
if (GetBilesenDurumu = 'Temel parametreler mükemmel') then begin
if NOT (csDesigning in ComponentState) then begin
FADS := TADODataSet.Create(Application);
with FADS do begin
Close;
Connection := FConnection;
CommandType := cmdText;
CommandText := GetSQL;
Open;
FGirebilir := NOT FADS.IsEmpty;
{ Sorgu sonucu BOŞ DEĞİL ve Sadece 1 KAYIT VAR İSE ! }
if (FGirebilir = True) AND (FADS.RecordCount = 1) then begin
if (FAlan_Key > '')
then FValue_Key := FieldByName(FAlan_Key).AsString;
if (FAlan_Hesap > '')
then FValue_Hesap := FieldByName(FAlan_Hesap).AsString;
if (FAlan_Yetkiler > '')
then FValue_Yetkiler:= FieldByName(FAlan_Yetkiler).AsString;
if (FAlan_Pasif > '' )
then FValue_Pasif := FieldByName(FAlan_Pasif).AsBoolean
end else begin
Sifirla;
end;
Close;
end;
FADS.Free;
end;
end;
except
// Hata verdirtmiyoruz...
end;
end;
procedure TupLoginDialog.Klik_Tus(Sender: TObject; var Key: Char);
begin
{ Klavyeden ESC'ye basıldığında KAPAT düğmesine basar}
{ ENDER'e basıldığında ise sonraki nesneye geçer... }
if (Key = #27) then Klik_Kapat(Sender) else
if (Key = #13) then begin
if (Sender = FCMB_Kullanici) then begin
if FCMB_Kullanici.Text>'' then begin
FEdit_Sifre.SetFocus
end;
end else
if (Sender = FEdit_Sifre) then begin
if (FEdit_Sifre.Text>'') then begin
FBTN_Giris.SetFocus;
FBTN_Giris.Click;
end;
end;
end;
end;
end.
Lookup'a Farklı Bir Yaklaşım (TupLookupDialog)
- 07 Ağustos 2009 Cuma
- Uğur Parlayan
Bu işe ilk başladığım zamanlarda üzerinde çok kafa yorduğum ama uzun bir süre çözemediğim yıldırıcı bir konu vardı, Lookuplar. Bildiğiniz gibi TDBLookupComboBox 1 tablodan tek bir kaydı seçmek için kullanılan, başka bir tabloya referans vermemizi sağlayan pratik bileşenlerden birisidir. Pratiktir pratik olmasına da veri miktarı arttığı zaman programın yavaş çalışmasına bir o kadar da sebep olurlar... Hele bir de ağ ortamında kullanıldığını düşünün, zahmetinden kullanılmaz bir programa sahip olursunuz... "Bu yazımda" Lookupların yaptığı işi daha hızlı yapan başka bir teknikten (ama ulu orta her yerde anlatılmayan özel bir) kod örneği vereceğim. umarım kıymetini bilir ve gereken ilgiyi gösterirsiniz...
TupLookupDialog Ne İşe Yarar
Bu bileşen, başka bir bileşenin çağırmasıyla devreye giren, etkinleştiğinde ise sizin belirttiğiniz tablodan ve o tablodaki primary key ve listelenen 2. bir alan aracılığıyla seçim yapmanızı sağlayan özel bir Pencere açar, bu pencerede aşağıda da göreceğiniz gibi bir arama alanı, çeşitli düğmeler ve bir liste bulunmaktadır. Lookuplar, bu pencerenin çok rafine, çok az işleve sahip olan bir kısmını kullanırlar, dolayısıyla hareket alanı ve rahatlığı sınırlıdır. Ayrıca Lookupların referans aldığı tabloların bellekte sürekli açık kalması gerektiği gibi bir sıkıntı da vardır. Bizim bileşenimizin böyle bir derdi yok. Sadece çağırıldığında devreye girer, size seçim yapmanız için listeyi getirir ve tamama bastığınızda veriyi istediğiniz değişkene devredip intihar eder. Böylece hem bellek israfından kurtulur hem de yükleme sırasındaki dakikalarca bekleme zahmetini de yaşamamış oluruz.

TupLookupDialog'un Kaynak Kodu
Aşağıda, size bu bileşenin kaynak kodunu veriyorum. Bu bileşen ile ilgili teknik detayları ayrı ayrı da anlatabilirdim fakat konu bütünlüğünün bozulmaması için gereken açıklamaları kodun içine serpiştirdim, neyi neden ve nerede yaptığımı böylece daha iyi anlatabileceğimi düşünüyorum... Bu arada bu kodun Veritabanı bilinçli sürümü de vardır ama bu size özel beleş sürüm olduğu için artık gerisini kendiniz yaparsınız :)
unit upLookupDialog;
interface
uses
SysUtils, Classes, StdCtrls, Mask, DBCtrls, DB, ExtCtrls, Controls, Buttons,
Variants, Messages, Graphics, Windows, Forms, Dialogs, ADODB, Grids, DBGrids;
type
TSQLTurleri = (MsSQL, MySQL); { SQL Cümlemizi bu standartlara göre "hesaplayacağız"... }
TupLookupDialog = class(TCommonDialog)
private
{Dialog penceresindeki özel nesnelerimiz...}
FPencere : TForm; { Dialog penceremizin formu }
FLabel : TLabel; { "Aranan" adlı bir text }
FAranan : TEdit; { Neyi arayacağımızı buna yazacağız }
FBul : TButton; { Bul düğmemiz }
FTemizle : TButton; { Temizle düğmemiz }
FTazele : TButton; { Tazele düğmemiz }
FOtomatikAra : TCheckBox; { İşaret kutucuğumuz, işaretlediğimizde yazarken bulacak}
FAdoDataSet : TAdoDataSet; { }
FDataSource : TDataSource; { }
FGrid : TDBGrid; { Verilerin listeleneceği yer }
FNavigator : TDBNavigator; { İleri/geri/ilk/son gibi düğmeler}
FOnizleme : TDBText; { Hangi verinin o an seçili olduğunu bundan göreceğiz}
FTamam : TButton; { SEÇ düğmemiz }
FNulle : TButton; { BOŞALT düğmemiz (NULL yapmak için)}
FVazgec : TButton; { Vazgeç düğmemiz... }
{Bileşenin kendine özgü diğer kısımları}
FConnection : TAdoConnection;
FTablo : String;
FFieldKey : String;
FFieldValue : String;
FKosul : String;
FValueData : String;
FValueKey : Variant; { İlla bir tamsayı olacak değil, string de olabilir}
FSQL : String;
FLimit : Integer;
FPencereBasligi : String;
FFieldValueAlias: String;
FYazarkenBul : Boolean;
FMetniBul : Boolean;
FSQLTuru : TSQLTurleri;
procedure SetConnection(const Value: TAdoConnection);
procedure Derle;
function GetSQLSorgu: string;
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
function GetDurum: String;
protected
procedure FormOlustur;
procedure TamamKlik(Sender: TObject);
procedure NulleKlik(Sender: TObject);
procedure VazgecKlik(Sender: TObject);
procedure BulKlik(Sender: TObject);
procedure TemizleKlik(Sender: TObject);
procedure TazeleKlik(Sender: TObject);
procedure PencereBoyutlandir(Sender: TObject);
procedure TusaBas(Sender: TObject; var Key: Char);
procedure AramaYap(Sender: TObject);
procedure OtomatikBuldur(Sender: TObject);
function MsQuoter(const Value: String): String;
function MyQuoter(const Value: String): String;
function SqlQuoter(const Value: String): String;
public
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
function Execute: Boolean; override;
{Dışarıdan bir referans verilirse formu açmadan tak diye sonucu çekmemizi sağlar}
function KeyOku(Value: Variant): String;
published
{Bağlantı nesnesi}
property Connection : TAdoConnection read FConnection write SetConnection;
{Kaynak Tablo}
property Tablo : string read FTablo write FTablo;
{Primary Key alanı}
property FieldKey : string read FFieldKey write FFieldKey;
{Listelenecek / Seçim / Arama yapılacak Alan}
property FieldValue : string read FFieldValue write FFieldValue;
property FieldValueAlias : string read FFieldValueAlias write FFieldValueAlias;
{WHERE koşulu alt cümleciği}
property Kosul : string read FKosul write FKosul;
{Toplam kaç kayıt gözükecek ?}
property Limit : integer read FLimit write FLimit default 0;
{Sonuç = Primary Key Value}
property ValueKey : variant read FValueKey;
{Sonuç = Seçim...}
property ValueData : string read FValueData write FValueData;
{Çalıştırılacak SQL Cümleciği... (MSSQL/T-SQL ve MySQL)}
property SQLSorgu : string read GetSQLSorgu;
{Lookup Penceresinin Başlığı...}
property PencereBasligi : string read FPencereBasligi write FPencereBasligi;
{Arama alanında bir harfe basılırken anında filtreyi devreye almayı sağlar...}
property YazarkenBul : Boolean read FYazarkenBul write FYazarkenBul default False;
{Form, açıldığı anda dışarıdan verilen metni kendi listesinden bulmaya yarar}
property MetniBul : Boolean read FMetniBul write FMetniBul default False;
{SQL'imiz hangi teknolojiyi kullanıyor?}
{Bu sorunun cevabı ürettiğimiz SQL cümlesini şekillendirecek.}
property SQLTuru : TSQLTurleri read FSQLTuru write FSQLTuru default MsSQL;
{Bileşenin hangi aşamada ne tür bir eksiğinin olduğunu anlamamızı sağlayacak.}
property Durum : String read GetDurum;
end;
procedure Register;
implementation
var
ExecuteSonucu: Boolean;
procedure Register;
begin
RegisterComponents('UgurPack2007', [TupLookupDialog]);
end;
{ TupLookupDialog }
procedure TupLookupDialog.AramaYap(Sender: TObject);
begin
{Klavyede bir tuşa basıldığında anında filtreyi uygular... Tabi Editteyken...}
if (Sender is TEdit) then begin
if (TEdit(Sender).Text>'')
and (FYazarkenBul = True) {Yazarken arama etkinleştirilmişse...}
then BulKlik(Sender);
{else TemizleKlik(Sender);(* ne gerek varki... *)}
end;
end;
procedure TupLookupDialog.BulKlik(Sender: TObject);
begin
{Bul düğmesine basıldığında listelenen alan içerisinde}
{aranan metni filtreler ve filtreyi açar...}
if Assigned(FAdoDataSet) then begin
with FAdoDataSet do begin
try
if (FFieldValueAlias > '')
then begin
case FSQLTuru of
MsSQL: Filter := MsQuoter(FFieldValueAlias) + ' LIKE ''%'+FAranan.Text+'%''';
MySQL: Filter := MyQuoter(FFieldValueAlias) + ' LIKE ''%'+FAranan.Text+'%''';
end;
end else begin
case FSQLTuru of
MsSQL: Filter := MsQuoter(FFieldValue) + ' LIKE ''%'+FAranan.Text+'%''';
MySQL: Filter := MyQuoter(FFieldValue) + ' LIKE ''%'+FAranan.Text+'%''';
end;
end;
Filtered := True;
except
nil;
end;
end;
end;
end;
constructor TupLookupDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
{Sadece bileşeni mantıken oluşturur, henüz ortada gözle görülen bir zımbırtı yok...}
end;
procedure TupLookupDialog.Derle;
var
AraKosul : string;
AraLimit : string;
Alias : string;
Siralayici : string;
begin
{MsSQL (T-SQL) veya MySQL uyumlu "optimize edilmiş" bir SQL cümlesi oluşturur}
{Bu kod birden fazla yerde kullanıldığı için ayrı bir prosedür olarak tasarlandı...}
FSQL := '';
if Assigned(FConnection) then begin
if (FTablo > '')
and(FFieldKey > '')
and(FFieldValue > '') then begin
case SQLTuru of
MsSQL:
Begin
{-FSQL-}
if (FKosul > '')
then AraKosul := FORMAT('WHERE %s',[FKosul])
else begin
AraKosul := '';
end;
if (FLimit > 0)
then AraLimit := FORMAT('TOP %d', [FLimit])
else AraLimit := '';
if (FFieldValueAlias>'') then begin
Alias := FORMAT(' AS [%s] ', [FFieldValueAlias]);
Siralayici := FFieldValueAlias;
end else begin
Alias := '';
Siralayici := FFieldValue;
end;
FSQL := FORMAT('SELECT %s [%s], %s %s FROM dbo.[%s] %s ORDER BY [%s]',
[AraLimit,FFieldKey,FFieldValue,Alias,FTablo,AraKosul,Siralayici]);
end;
MySQL:
Begin
{-FSQL-}
if (FKosul > '')
then AraKosul := FORMAT('WHERE %s',[FKosul])
else begin
AraKosul := '';
end;
if (FLimit > 0)
then AraLimit := FORMAT(' LIMIT %d', [FLimit])
else AraLimit := '';
if (FFieldValueAlias>'') then begin
Alias := FORMAT(' AS `%s` ', [FFieldValueAlias]);
Siralayici := FFieldValueAlias;
end else begin
Alias := '';
Siralayici := FFieldValue;
end;
FSQL := FORMAT('SELECT [%s], %s %s FROM `%s` %s ORDER BY [%s] %s',
[FFieldKey,FFieldValue,Alias,FTablo,AraKosul,Siralayici,AraLimit]);
End;
end; {case !}
end; {if}
end; {if assigned}
end;
destructor TupLookupDialog.Destroy;
begin
{Tıpkı atalarından aldığı bir huy gibi her şeyi yok eder...}
inherited Destroy;
end;
function TupLookupDialog.Execute: Boolean;
begin
{Dış ortamın talebiyle devreye girer, formu oluşturup seçim yapılmasını bekler.}
{Akabinde seçim yapıldıysa seçilenleri dışa aktarır ve pencerenin kapanmasını sağlar...}
Result := False;
Derle;
if (FSQL>'') then begin
try
FormOlustur;
FPencere.ShowModal;
finally
FPencere.Free;
Result := ExecuteSonucu;
end;
end;
end;
procedure TupLookupDialog.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
{Aşağı yön tuşuna basıldıysa Gride fokuslanır...}
if Key = VK_DOWN then FGrid.SetFocus;
end;
procedure TupLookupDialog.FormOlustur;
const
sbt_Aralik = 4; { Penceredeki düğmeler arasındaki boşluk (Pixel cinsinden...)}
sbt_Padding = 10;
begin
try
{Dialog penceresini tüm unsurlarıyla birlikte üretir.}
FPencere := TForm.Create(Application.Owner);
with FPencere do begin
Position := poMainFormCenter;
KeyPreview := True;
Caption := FPencereBasligi;
ShowHint := True;
Width := 550;
Height := 400;
with Constraints do begin
MinWidth := 350;
MinHeight := 200;
end;
BorderStyle := bsSizeable;
OnPaint := PencereBoyutlandir;
OnKeyDown := FormKeyDown; {Özel bir tuşa basılırsa...}
{OnResize := PencereBoyutlandir; Bunu kullanmıyoruz,}
{Çünkü nesne henüz "üretim" aşamasında olduğu için OnResize}
{olayı anında devreye giriyor ve hata üretiyor. Bunu önlemek için}
{bu kısma bir değer atamıyoruz. Belki OnPaint olayına tanımlanabilir.}
{Show; Bunu özellikle çalıştırmadık...}
end;
FLabel := TLabel.Create(FPencere);
with FLabel do begin
Parent := FPencere;
Left := sbt_Padding;
Top := sbt_Padding + 2;
Height := 17;
Caption := 'Aranan : ';
AutoSize := True; {Kendi genişliğini kendisi ayarlasın...}
Show;
end;
FAranan := TEdit.Create(FPencere);
with FAranan do begin
Parent := FPencere;
BevelKind := bkTile;
BorderStyle := bsNone;
Height := 20;
Top := sbt_Padding;
Left := FLabel.Left + FLabel.Width + sbt_Aralik;
Width := FPencere.ClientWidth
- Left
- sbt_Padding
- 140 { sağdaki 3 butonun eni }
- (sbt_Aralik * 3);
if (FValueData>'')
then Text := FValueData
else Text := '';
OnKeyPress := TusaBas;
OnChange := AramaYap;
Anchors := [akLeft,akTop,akRight]; { Pencere boyu değiştiğinde uyum sağlasın }
Hint := 'Enter = Yazılanı bulur, ESC = 1.de satırı siler 2.de "Vazgeç"e basar.';
Show;
end;
FBul := TButton.Create(FPencere);
with FBul do begin
Caption := '&Bul';
Anchors := [akRight,akTop];
Parent := FPencere;
Default := False;
Width := 40;
Height := FAranan.Height;
Top := FAranan.Top;
Left := FPencere.ClientWidth - sbt_Padding - (140) - (sbt_Aralik * 2);
Hint := 'Sol tarafa yazdığınız metni bulur...';
OnClick := BulKlik;
OnKeyPress := TusaBas;
Show;
end;
FTemizle := TButton.Create(FPencere);
with FTemizle do begin
Caption := 'Te&mizle';
Anchors := [akRight,akTop];
Parent := FPencere;
Width := 50;
Height := FAranan.Height;
Top := FAranan.Top;
Left := FPencere.ClientWidth - sbt_Padding - (100) - (sbt_Aralik );
Hint := 'Sol tarafı temizler ve listeyi açar';
OnClick := TemizleKlik;
OnKeyPress := TusaBas;
Show;
end;
FTazele := TButton.Create(FPencere);
with FTazele do begin
Caption := 'Ta&zele';
Anchors := [akRight,akTop];
Parent := FPencere;
Top := FAranan.Top;
Width := 50;
Height := FAranan.Height;
Left := FPencere.ClientWidth - sbt_Padding - (50);
OnClick := TazeleKlik;
Hint := 'Aşağıdaki listenin en son halini sorgular';
OnKeyPress := TusaBas;
Show;
end;
FOtomatikAra := TCheckBox.Create(FPencere);
with FOtomatikAra do begin
Parent := FPencere;
Top := 33;
Left := FAranan.Left;
Caption := 'Yazarken süz...';
OnClick := OtomatikBuldur;
Checked := FMetniBul;
Show;
end;
FAdoDataSet := TAdoDataSet.Create(FPencere);
with FAdoDataSet do begin
Connection := FConnection;
CommandType := cmdText;
CommandText := FSQL;
end;
FDataSource := TDataSource.Create(FAdoDataSet);
with FDataSource do begin
DataSet := FAdoDataSet;
AutoEdit := False;
end;
FGrid := TDBGrid.Create(FPencere);
with FGrid do begin
Parent := FPencere;
Left := sbt_Padding;
Top := FAranan.Top + FAranan.Height + sbt_Aralik + FOtomatikAra.Height;
Width := FPencere.ClientWidth - Left - sbt_Padding;
Height := FPencere.ClientHeight - Top - (sbt_Padding * 2) - FOtomatikAra.Height;
Anchors := [akLeft,akTop,akRight,akBottom];
Options := [dgTitles,dgRowLines,dgAlwaysShowSelection
,dgConfirmDelete,dgCancelOnExit];
DataSource := FDataSource;
OnDblClick := TamamKlik;
OnKeyPress := TusaBas;
Columns.Add;
Show;
end;
FNavigator := TDBNavigator.Create(FPencere);
with FNavigator do begin
Parent := FPencere;
Anchors := [akLeft,akBottom];
VisibleButtons := [nbFirst,nbPrior,nbNext,nbLast];
Left := sbt_Padding;
Top := FGrid.Top + FGrid.Height + sbt_Padding;
Width := 125;
Height := 20;
Flat := True;
DataSource := FDataSource;
end;
FOnizleme := TDBText.Create(FPencere);
with FOnizleme do begin
Parent := FPencere;
Anchors := [akBottom,akLeft,akRight];
Top := FGrid.Top + FGrid.Height + sbt_Padding;
Left := sbt_Padding + FNavigator.Width + sbt_Aralik;
Height := 20;
Width := FPencere.ClientWidth - Left - sbt_Padding - (55 * 3) - (4 * 3);
AutoSize := False; {Kendi genişliğini kendisi ayarla"MA"sın...}
DataSource := FDataSource;
Color := clAppWorkSpace;
if (FFieldValueAlias>'')
then DataField := FFieldValueAlias
else DataField := FFieldValue;
TLabel(FOnizleme).Layout := tlCenter;
Hint := 'Eğer "SEÇ"e basarsanız bunu seçeceksiniz.';
Show;
end;
try
FAdoDataSet.Open;
{Daha hızlı çalışması için tüm nesneleri}
{oluşturduktan sonra çekiyoruz verilerimizi...}
except
NULL;
end;
if (FMetniBul = True) then BulKlik(FBul);
with FGrid.Columns.Items[0] do begin
Field := FAdoDataSet.Fields.Fields[1];
Title.Caption := 'Listeden bir satır seçin ve "SEÇ" veya "Enter" tuşuna basın. '
+ 'İptal için "ESC"yi kullanabilirsiniz. ';
Title.Color := clInfoBk;
Title.Font.Color := clInfoText;
Width := FGrid.ClientWidth;
end;
FTamam := TButton.Create(FPencere);
with FTamam do begin
Caption := '&SEÇ';
Anchors := [akRight,akBottom];
Parent := FPencere;
Width := 55;
Left := FPencere.ClientWidth - sbt_Padding - (Width * 3) - (sbt_Aralik * 2);
Top := FGrid.Top + FGrid.Height + sbt_Padding;
Height := 20;
Hint := 'Soldaki metinde de gösterilen veriyi seçersiniz...';
OnClick := TamamKlik;
Show;
end;
FNulle := TButton.Create(FPencere);
with FNulle do begin
Caption := 'B&oşalt';
Anchors := [akRight,akBottom];
Parent := FPencere;
Width := 55;
Left := FPencere.ClientWidth - sbt_Padding - (Width * 2) - (sbt_Aralik);
Top := FGrid.Top + FGrid.Height + sbt_Padding;
Height := 20;
Hint := '"BOŞ" seçilir, önceden seçilmiş bir değer varsa yok olur...';
OnClick := NulleKlik;
Show;
end;
FVazgec := TButton.Create(FPencere);
with FVazgec do begin
Caption := '&Vazgeç';
Anchors := [akRight,akBottom];
Parent := FPencere;
Width := 55;
Left := FPencere.ClientWidth - sbt_Padding - Width;
Top := FGrid.Top + FGrid.Height + sbt_Padding;
Height := 20;
Hint := 'Hiç bir seçim yapmadan pencereyi kapatır.';
OnClick := VazgecKlik;
Show;
end;
except
nil;
end;
end;
function TupLookupDialog.GetDurum: String;
var
Sonuc: String;
begin
{ Bu bileşen için gerekli olan kritik değişkenler hakkında dış ortama bilgi verir. }
Sonuc := '';
if not Assigned(FConnection) then Sonuc := Sonuc + 'Bağlantı nesnesi eksik. ';
if FTablo = '' then Sonuc := Sonuc + 'Tablo adı belirtilmemiş. ';
if FFieldKey = '' then Sonuc := Sonuc + 'Anahtar alan adı belirtilmemiş. ';
if FFieldValue = '' then Sonuc := Sonuc + 'Listelenecek alan adı belirtilmemiş. ';
if FPencereBasligi = '' then Sonuc := Sonuc + 'Pencere başlığı belirtilmemiş. ';
if FSQL = '' then Sonuc := Sonuc + 'SQL üretilemedi. ';
if Sonuc = '' then Sonuc := 'Herşey mükemmel.';
Result := Sonuc;
end;
function TupLookupDialog.GetSQLSorgu: string;
begin
{SQL Cümlesini dışarısının okuması için önce derler sonra dışa verir...}
Derle;
Result := FSQL;
end;
function TupLookupDialog.KeyOku(Value: Variant): String;
var
DS: TAdoDataSet;
SQL: String;
Alyas: String;
begin
{Bu fonksiyon eski kaynak kodda yoktu, sonradan böyle bir güzellik de eklemiş olduk...}
{Bu zımbırtının temelde yaptığı iş verilen keye göre ilgili liste alanının değerini çekiyor.}
Result := '>';
if not VarIsNull(Value)
and Assigned(FConnection) then begin
{Burası önemli, çünkü gelen key değeri bir string ise tırnak içine}
{almamız gerekir, yoksa SQL cümlemiz hata üretir...}
if VarIsStr(Value) then Value := ''+Value+'';
try
if (FFieldValueAlias>'') then begin
Alyas := FORMAT(' %s as '+SqlQuoter('%s'),[FFieldValue, FFieldValueAlias]);
end else begin
Alyas := FFieldValue;
end;
case FSQLTuru of
MsSQL: SQL := FORMAT('SELECT TOP 1 %s FROM %s WHERE %s = %s',
[Alyas, FTablo, FFieldKey, Value]);
MySQL: SQL := FORMAT('SELECT %s FROM %s WHERE %s = %s LIMIT 1, 1',
[Alyas, FTablo, FFieldKey, Value]);
end;
try
DS := TAdoDataSet.Create(Application.Owner);
with DS do begin
Connection := FConnection;
CommandType := cmdText;
CommandText := SQL;
Open;
end;
except
NULL;
end;
if not DS.IsEmpty then begin
if (FFieldValueAlias>'')
then Result := DS.FieldByName(FFieldValueAlias).AsString
else Result := DS.FieldByName(FFieldValue).AsString;
end;
finally
DS.Free;
DS := nil;
end;
end;
end;
function TupLookupDialog.MsQuoter(const Value: String): String;
begin
{T-SQL'e uyumlu bir paranteze alma işlemidir.}
{Alan Adları boşluk içeriyorsa [] parantezine alınır...}
Result := FORMAT('[%s]', [Value]);
end;
function TupLookupDialog.MyQuoter(const Value: String): String;
begin
{My SQL'e uyumlu bir tırnak içine alma işlemidir.}
{Alan Adları boşluk içeriyorsa `` içine alınır...}
Result := FORMAT('`%s`', [Value]);
end;
procedure TupLookupDialog.PencereBoyutlandir(Sender: TObject);
begin
{Gönderen mevcutsa ve FGrid varsa gridin içindeki kolonun enini gride sığdırır...}
if Assigned(Sender) then begin
if Assigned(FGrid) then begin
if (FGrid.Columns.Count>0) then
FGrid.Columns[0].Width := FGrid.ClientWidth;
end;
end;
end;
procedure TupLookupDialog.SetConnection(const Value: TAdoConnection);
begin
{TAdoConnection nesnesini dışarıdan alır ve bize bağlar...}
FConnection := Value;
end;
function TupLookupDialog.SqlQuoter(const Value: String): String;
begin
case FSQLTuru of
MsSQL: Result := MsQuoter(Value);
MySQL: Result := MyQuoter(Value);
end;
end;
procedure TupLookupDialog.TamamKlik(Sender: TObject);
begin
{Dışarısı için verileri hazırlar ve pencereyi kapatır...}
if (Assigned(FPencere)) then begin
FValueKey := FAdoDataSet.FieldByName(FFieldKey).AsVariant;
if (FFieldValueAlias > '')
then FValueData := FAdoDataSet.FieldByName(FFieldValueAlias).AsString
else FValueData := FAdoDataSet.FieldByName(FFieldValue).AsString;
ExecuteSonucu := True;
FPencere.Close; {Bu olmazsa kapanmaz!}
end;
end;
procedure TupLookupDialog.NulleKlik(Sender: TObject);
begin
{Eğer seçilmiş bir değeri boşaltmak istiyorsak bu kod devreye girecek...}
if (Assigned(FPencere)) then begin
FValueKey := NULL;
if (FFieldValueAlias > '')
then FValueData := ''
else FValueData := '';
ExecuteSonucu := True;
FPencere.Close; {Bu olmazsa kapanmaz!}
end;
end;
procedure TupLookupDialog.OtomatikBuldur(Sender: TObject);
begin
{ Metin kutusuna bir şey yazarken aynı anda arama yapılmasını da sağlar }
FYazarkenBul := FOtomatikAra.Checked;
BulKlik(Sender);
end;
procedure TupLookupDialog.TazeleKlik(Sender: TObject);
begin
{ Listemizdeki verilerin son halini veritabanından çeker }
if Assigned(FAdoDataSet) then begin
case FSQLTuru of
MsSQL: begin
FAdoDataSet.Requery;
end; {MsSQL}
MySQL: begin
FAdoDataSet.Close;
FAdoDataSet.Open;
end; {MySQL}
end; {case}
end;
end;
procedure TupLookupDialog.TemizleKlik(Sender: TObject);
begin
{ Filtreyi kapatıp tüm verileri listelenmesini sağlar... }
if Assigned(FAdoDataSet) then FAdoDataSet.Filtered := False;
end;
procedure TupLookupDialog.TusaBas(Sender: TObject; var Key: Char);
begin
{ 1) Edit'te iken ESC'ye basılırsa;}
{ a) Doluysa sadece temizle}
{ b) Boşsa, sıfırla ve pencereyi kapat}
{ 2) Enter tuşuna basıldıysa verileri dışarı aktar ve pencereyi kapat}
FYazarkenBul := FOtomatikAra.Checked;
if (Key = #27) then begin
if (Sender is TEdit)
then begin
if (TEdit(Sender).Text='')
then VazgecKlik(Sender)
else begin
TEdit(Sender).Text := '';
TemizleKlik(Sender)
end;
end
else VazgecKlik(Sender);
end else
if (Key = #13) then begin
if (Sender is TEdit) then begin
if (FYazarkenBul = True)
then begin
TamamKlik(Sender);
end else begin
if (TEdit(Sender).Text>'') then begin
BulKlik(Sender);
if (FAdoDataSet.RecordCount = 1)
then TamamKlik(Sender)
else FGrid.SetFocus;
end;
end;
end else
if (Sender is TDBGrid) then begin
TamamKlik(Sender);
end;
end;
end;
procedure TupLookupDialog.VazgecKlik(Sender: TObject);
begin
{Pencere varsa vazgeç düğmesinin işlevlerine boş değer ataması yapıp kapatıyoruz...}
if (Assigned(FPencere)) then begin
FValueKey := Variant(0);
FValueData := '';
ExecuteSonucu := False;
FPencere.Close; {Bu olmazsa kapanmaz!}
end;
end;
end.
Butonlu Edit Nesnesi (TupEditButon)
- 06 Ağustos 2009 Perşembe
- Uğur Parlayan
Son zamanlarda kendimi programlamaya verdim ve Delphicilerin faydalanacağına emin olduğum bir nesnenin kaynak kodlarını burada yayınlamaktan mutluluk duyuyorum. "Gerekli miydi?" derseniz, "nerede kullanacağınıza bağlı" derim. Lafı döndürmeye gerek yok, doğrudan konuya girelim;
TupEditButon ne işe yarar
Bu bileşen, tek satırlık bir metin kutusudur (TEdit), fakat diğer metin kutularından farklı olarak bir de dahili bir buton içerir. Çok yoğun formlarda böyle şeyler genelde aranılan bileşenlerdir, gerek yer sıkıntısı yaşanmaması adına, gerekse görüntü kirliliği oluşturmaması açısından ve biraz da simetri hastası delphiciler bu tür bileşenleri daha çok tercih eder. Üstelik kullanıcılar da bu tür özellikleri daha çabuk kapar ve kısa sürede kullanımına alışırlar. Son olarak bu tür bir bileşeni çeşitlendirerek kendine özgü bileşen paketleri de üretebilme kolaylığınız vardır çünkü gayet sade ve gayet işlevsel bir kaynak koda sahiptir. Eğer aşağıdaki kaynak kodu doğru şekilde işlerseniz daha farklı bir çok yetenek kazandırabilirsiniz.
Hatırlatma açısından değinmekte fayda var, kod aralarına yeni paragraflar ekleyerek kodun bütünlüğünü, kolay anlaşılabilirliğini parçalamak istemedim, o nedenle gerekli açıklamaları kaynak kodun içinden okuyabilirsniz, ayrıca bu kaynak kodu Delphi 2007'de halâ kullanmaktayım (Tabi çok daha gelişmiş başka bir sürümünü :)
{******************************************************************************}
{* *}
{* Programlayan: Uğur Parlayan (ugurparlayan@gmail.com) *}
{* Tarih: 06.08.2009 *}
{* *}
{* Kullanım: Ayrım gözetmeksizn külliyatıyla ÜCRETSİZDİR *}
{* Yazarın gönlü olsun diye kaynak belirtirseniz sevinirim... *}
{* *}
{* URL: http://www.kavramca.com/index.php?k=31 *}
{* *}
{******************************************************************************}
unit upEditButon;
interface
uses
SysUtils, Classes, StdCtrls, Mask, DBCtrls, DB, ExtCtrls, Controls,
Buttons, Messages, Graphics, Windows, Forms, Dialogs;
type
TupEditButon = class(TEdit)
private
FButon: TButton;
function GetMinHeight: Integer;
procedure SetEditRect;
procedure WMSize(var Message: TWMSize); message WM_SIZE;
function GetOnButonClick: TNotifyEvent;
procedure SetOnButonClick(const Value: TNotifyEvent);
protected
procedure CreateWnd; override;
procedure KeyPress(var Key: Char); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure CreateParams(var Params: TCreateParams); override;
property Button: TButton read FButon;
published
{OnButonClick: Bu özellik butonumuza basılıp basılmadığını yönetecek...}
Property OnButonClick: TNotifyEvent read GetOnButonClick write SetOnButonClick;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Ugur', [TupEditButon]);
end;
{ TupEditButon }
constructor TupEditButon.Create(AOwner: TComponent);
var
En: integer;
begin
{Ana nesneyi oluşturduk}
inherited Create(AOwner);
{Butonu üretiyoruz}
En := 20;
FButon := TButton.Create (Self);
with FButon do begin
Parent := Self;
Caption := '...';
{ Buton.Brush.Bitmap.Canvas.TextWidth(FButon.Caption); }
{ Yukarıdaki satır nesne henüz oluşum aşamasında olduğu için hata veriyor }
{ O nedenle "EN" değişkenine sabit bir değer verildi... }
Height := 16;
Width := En;
Left := Self.Width - En - 1;
Text := ''; {Buraya bir başlangıç değeri verilebilir...}
Visible := True;
end;
ControlStyle := ControlStyle - [csSetCaption];
end;
procedure TupEditButon.CreateParams(var Params: TCreateParams);
begin
{Bu prosedür bu bileşene bağlı alt bileşenlere parametre göndermekte kullanılır...}
inherited CreateParams(Params);
Params.Style := Params.Style or ES_MULTILINE or WS_CLIPCHILDREN;
end;
procedure TupEditButon.CreateWnd;
begin
{Yazı alanının belli bir bölgede sınırlanmasına yardım eder...}
inherited CreateWnd;
SetEditRect;
end;
destructor TupEditButon.Destroy;
begin
{Nesne yok edilirken bağlı diğer nesneler de yokedilir.}
FButon := nil;
inherited Destroy;
end;
function TupEditButon.GetMinHeight: Integer;
var
DC: HDC;
SaveFont: HFont;
I: Integer;
SysMetrics, Metrics: TTextMetric;
begin
{Metin alanının kaç pizel yükseklikte olduğunu hesaplar.}
DC := GetDC(0);
GetTextMetrics(DC, SysMetrics);
SaveFont := SelectObject(DC, Font.Handle);
GetTextMetrics(DC, Metrics);
SelectObject(DC, SaveFont);
ReleaseDC(0, DC);
I := SysMetrics.tmHeight;
if I > Metrics.tmHeight then I := Metrics.tmHeight;
Result := Metrics.tmHeight + I div 4 + GetSystemMetrics(SM_CYBORDER) * 4 + 2;
end;
function TupEditButon.GetOnButonClick: TNotifyEvent;
begin
{Olay tetiklendiğinde bizim butona yönlendirilecek...}
Result := FButon.OnClick;
end;
procedure TupEditButon.KeyPress(var Key: Char);
begin
inherited;
{Enter'e basılınca alt satıra geçmesin, bi düdük çalsın...}
if Key = #13 then begin
Key := #0;
MessageBeep(0);
end;
{entere basılmamışsa tuşu devreye al...}
if not(Key in [#0,#13]) then inherited KeyPress(Key);
end;
procedure TupEditButon.SetEditRect;
var
Kutu: TRect;
begin
{yazı alanının belli bir sınır içine alınmasını sağlar...}
{$IFNDEF TMSDOTNET}
SendMessage(Handle, EM_GETRECT, 0, LongInt(@Kutu));
{$ENDIF}
{$IFDEF TMSDOTNET}
Perform(EM_GETRECT, 0, Kutu);
{$ENDIF}
Kutu.Bottom := ClientHeight + 1;{windowsun paint zımbırtısının bir buguymuş}
Kutu.Right := ClientWidth - FButon.Width - 1;
Kutu.Top := 0;
Kutu.Left := 0;
{$IFNDEF TMSDOTNET}
SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@Kutu));
SendMessage(Handle, EM_GETRECT, 0, LongInt(@Kutu)); {dibagçün...}
{$ENDIF}
{$IFDEF TMSDOTNET}
Perform(EM_SETRECTNP, 0, Kutu);
Perform(EM_GETRECT, 0, Kutu);
{$ENDIF}
end;
procedure TupEditButon.SetOnButonClick(const Value: TNotifyEvent);
begin
{Editteki butona basılazak...}
FButon.OnClick := Value;
end;
procedure TupEditButon.WMSize(var Message: TWMSize);
var
Boy: Integer;
begin
inherited;
Boy := GetMinHeight;
{Edit nesnesinin bir buguymuş. Bu işlem yapılmazsa nesne büzüşür...}
if (Height < Boy) then
Height := Boy
else
if (FButon <> nil) then begin
if NewStyleControls and Ctl3D
then FButon.SetBounds(Width - FButon.Width - 4, 0, FButon.Width, Height - 4)
else FButon.SetBounds(Width - FButon.Width, 1, FButon.Width, Height - 2);
SetEditRect;
end;
end;
end.
HatırlatmaBu sayfa test aşamasında olup deneysel veriler içermektedir.
Cıvıltılar- Herkes aynı fikirdeyse, hiç kimse yeterince düşünmüyor demektir
- Beleş malın ömrü kısa olur
- Bütün mucitler tembel olsaydı cilalıtaş devrine yeni girmiştik...
- Çaresizlik insana icat yaptırır...
- Yüzyılın Soykırımı
- Sparkfun elektronik 7 Ocak 2010'da 1000 kişiye 100$ değerinde hediye dağıtacakmış...
- Muharrem Ankara'da işbaşı yaptı, kendisine başarılı ve müreffeh bir iş hayatı diliyoruz :)
- Erhan'a da huzurlu ve mutlu bir ömür diliyoruz.
- MikroPascal'ın LCD kütüphanesinde ne tür bir sorun olabilir AÇAPAAAA! Nerede bu kodlar, nerede bu kaynak kodlar !!!
Sayfa Seç1 2 Toplam 2 sayfa var. Siz 1. sayfadasınız ve 4 kayıt içinden 1 ile 3 arasını görmektesiniz
Yazı MiktarıBu sayfada kaç adet yazı görmek istiyorsunuz? Aşağıdakilerden birini seçiniz 1
2
3
5
10
15
20
30
50
75
100
200
300
|