Delphi'de ListView ile Telefon Rehberi

Delphi kullanırken ListView bileşenini biraz ihmal ettiğimi söyleyebilirim. Bu yazıda Windows'un kendi bileşenlerinden olan ListView'İ(Denetim masası bir ListView'dır) bir telefon defteri projesinde kullanarak inceleyeceğim. Ayrıca kullanıcıdan çok satırlı bilgi alma, Auto-create forms ve formlar arası veri aktarımı gibi konulara da değineceğim.

Programımızın bitmiş hali şu şekilde görünecek:

 

ListView bileşeninde her sütunun bir başlığı ve alt parçaları bulunuyor.

Delphi'de yeni bir VCL Forms Application oluşturduktan sonra, forma bir tane ListView bileşeni koyuyoruz. Bileşenin adını lv1, Align özelliğini ise alClient olarak ayarlıyoruz. Bu Align ayarı sayesinde ListView tüm formu kaplayacak ve bu şekilde formun boyutunu değiştirerek ListView'in de boyutlarını değiştirebileceğiz. Forma bir tane de PopupMenu bileşeni koyup adını pmnu1 olarak ayarlıyoruz. lv1'in PopupMenu özelliğini pmnu1 olarak değiştiriyoruz. Böylece lv1'in üzerinde sağ tıklanınca karşımıza pmnu1 gelecek. pmnu1'in Menu Designer ile şu şekilde tasarlıyoruz:

Formun Create olayında, lv1'in bazı özelliklerini aşağıdaki gibi değiştiriyoruz. Aşağıdaki kodda, programın exe dosyasının çalıştığı yeri veren bir de fonksiyon yer alıyor.

function GecerliKlasoruAl: string;
begin
  Result := ExtractFilePath(Application.ExeName);
  if Result[Length(Result)] <> '' then
   Result := Result + '';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  lv1.Clear;
  lv1.ViewStyle:=vsReport;
  lv1.RowSelect:=true;
  lv1.Columns.Add;
  lv1.Columns.Items[0].Caption:='No';
  lv1.Columns.Items[0].Width:=35;
  lv1.Columns.Add;
  lv1.Columns.Items[1].Caption:='Ad';
  lv1.Columns.Items[1].Width:=140;
  lv1.Columns.Add;
  lv1.Columns.Items[2].Caption:='Soyad';
  lv1.Columns.Items[2].Width:=140;
  lv1.Columns.Add;
  lv1.Columns.Items[3].Caption:='Telefon';
  lv1.Columns.Items[3].Width:=100;
  lv1.Columns.Add;
  lv1.Columns.Items[4].Caption:='Not';
  lv1.Columns.Items[4].Width:=200;
  if fileexists(GecerliKlasoruAl+'lv.txt') then
    ListViewLoadFromFile(lv1, GecerliKlasoruAl+'lv.txt');
end;

Buradaki kodları açıklayacak olursak, 10. satırda ListView'ın tüm elemanlarını siliyoruz. 11. satırda ListView'ı rapor görünümüne ayarlıyoruz. Alttaki diğer satırlarda ListView'a sütun ekleyip, sütun başlıklarını ve genişliklerini ayarlıyoruz. 28. satırda daha evvel rehbere kaydedilmiş bilgiler varsa bunları lv1'e yüklüyoruz.

Sıra da ListView'a yeni bir rehber kaydının eklenmesi var. Burada karşımıza bir takım problemler çıkıyor. Delphi'de kullanıcıdan bilgi girişi almanın en kolay yolu InputBox kullanmak. Ancak InputBox'la kullanıcıdan sadece bir bilgi alabilirz. Bizim programımızda ise Ad, Soyad, Telefon ve Not gibi dört tane bilgi almamız gerekiyor. Bu durumda yapmamız gerken, bilgi girişi için bir form tasarlamak. Bu formu aşağıdaki gibi tasarlıyoruz.

 

Yukarıda da görüldüğü formda 4 label, 4 edit, 2 tane de BitBtn bileşeni var. Bu formda bileşenlerin isimlerini varsayılan ayarlarda bırakıyorum. Ancak düğmelerin Kind özelliklerini sırasıyla bkOK ve bkCancel olarak ayarlıyorum. Bu hem düğmelerin üzerindeki resimlerin otomatik görünmesini sağlayacak, hem de düğmelere basıldığında form otomatik olarak kapanacak. Ayrıca hangi düğmeye basıldığını anlamamızı sağlayacak bir ModalResult üretilecek.

Yine burada başka bir durumdan da bahsetmemiz lazım. Delphi projelerinde, proje çalıştığında aksine bir ayar yapılmamışsa tüm formlar otomatik olarak hafızaya yüklenir. Bizim uygulamamızda son hazırladığımız formun devamlı hafızada olmasına gerek yok. Sadece gerektiği zaman formun Create edilmesi yeterli. Bunu sağlayabilmek için Project menüsünden Options'u seçiyoruz, Forms bölümünden Form2'yi > düğmesi ile Auto-create forms bölümünden Available forms bölümüne taşıyoruz.

pmnu1'den Yeni Kayıt seçildiğinde yapılacak işlemlere geldi sıra. Öncekikle Yeni Kayıt'ı çift tıklayıp aşağıdaki kodları yazıyoruz.

procedure TForm1.Y1Click(Sender: TObject);
begin
  with TForm2.Create(Self) do
  try
    islem:='y';
    if ShowModal=mrOK then
    begin

    end;
  finally
    Free;
  end;
end;

Bu kodda 3. satırda formu Create ediyoruz. Bu formu yeni kayıt eklemenin yanı sıra, kayıt düzeltmede de kullanacağız. Aradaki ayrımı belirtebilmek için formun public kısmında tanımladığımız islem adlı char değişkene 5. satırda yeni kaydı ifade eden y değerini atıyoruz. 6. satırdaki if bölümü hiçbir iş yapmıyor gibi görünse de, formun ekranda görünmesini bu satır sağlıyor.

Burada karşımıza tekrar bir sorun çıkıyor. Bir formdan diğer bir forma nasıl veri aktaracağız? Bunu yapabilmek için her iki formun da unit dosyalarında implementation bölümünün aldında uses kısmında unit adlarını ekliyoruz. Bu sayede form isimlerini kullarak her iki formdan da istenilen formdaki bileşenlere ulaşabileceğiz. Veri girişi için hazırladığımız formdaki Tamam düğmesindeki kodlar bu sebepten şu şekilde oluyor:

procedure TForm2.BitBtn1Click(Sender: TObject);
begin
  if Form1.islem='y' then  //yeni kayıt ekleniyorsa
  begin
    Form1.lv1.Items.Add;
    Form1.lv1.Items.Item[Form1.lv1.Items.Count-1].Caption:=inttostr(Form1.lv1.Items.Count);
    Form1.lv1.Items.Item[Form1.lv1.Items.Count-1].SubItems.Add(Edit1.Text);
    Form1.lv1.Items.Item[Form1.lv1.Items.Count-1].SubItems.Add(Edit2.Text);
    Form1.lv1.Items.Item[Form1.lv1.Items.Count-1].SubItems.Add(Edit3.Text);
    Form1.lv1.Items.Item[Form1.lv1.Items.Count-1].SubItems.Add(Edit4.Text);
  end
  else if Form1.islem='d' then //düzeltme yapılıyorsa
  begin
    Form1.lv1.Selected.SubItems[0]:=edit1.Text;
    Form1.lv1.Selected.SubItems[1]:=edit2.Text;
    Form1.lv1.Selected.SubItems[2]:=edit3.Text;
    Form1.lv1.Selected.SubItems[3]:=edit4.Text;
  end;
end;

Düzeltme bölümü için lv1'deki herhangi bir kaydın üzerinde sağ tıklanmasını beklememiz lazım. pmnu1'de Düzelt kısmını çift tıklayıp, kodları şu şekilde yazıyoruz.

procedure TForm1.Dzelt1Click(Sender: TObject);
begin
  if lv1.Selected=nil then
    raise Exception.Create('Hiçbir kayıt seçmediniz');
  islem:='d';
  with TForm2.Create(Self) do
  try
    edit1.Text:=lv1.Selected.SubItems[0];
    edit2.Text:=lv1.Selected.SubItems[1];
    edit3.Text:=lv1.Selected.SubItems[2];
    edit4.Text:=lv1.Selected.SubItems[3];
    if ShowModal=mrOK then
    begin

    end;
  finally
    Free;
  end;
end;

3. satırda seçili satır olup olmadığını kontrol edip, seçili satır yoksa bir istisna oluşturuyoruz. Eğer seçili satır varsa, 6. satırda oluşturulan formdaki edit'lere , lv1'deki bilgileri aktarıyoruz.

Satır silme işlemini de benzer mantıkla şu şekilde kodluyoruz:

procedure TForm1.Sil1Click(Sender: TObject);
begin
  if lv1.Selected =nil then
    raise Exception.Create('Hiçbir kayıt seçmediniz');
  If Application.MessageBox('Emin misiniz?', '', MB_YESNO+MB_ICONQUESTION+MB_DEFBUTTON2+MB_APPLMODAL) = ID_NO Then
    Exit;
  lv1.ItemFocused.Free;
end;

ListView bileşenin ListBox'ta olduğu gibi LoadFromfile ya da SaveToFile gibi yordamları yok. O yüzden StackOverflow'da bulduğum aşağıdaki kodları bu işler için kullandım. Burada dikkat edilecek nokta,  ListView'daki sütunları aralarına Tab karakteri(#9) koyarak kaydedildiği.

procedure ListViewSaveToFile(ListView: TListView; const FileName: string);
  procedure AddTextToLine(var Line: string; const Text: string);
  begin
    Line := Line + Text + #9;
  end;
  procedure MoveCompletedLineToList(const Strings: TStringList; var Line: string);
  begin
    Strings.Add(System.Copy(Line, 1, Length(Line)-1));//remove trailing tab
    Line := '';
  end;
var
  Strings: TStringList;
  LatestLine: string;
  i, j: Integer;
begin
  LatestLine := '';
  Strings := TStringList.Create;
  try
    for i := 0 to ListView.Items.Count-1 do
    begin
      AddTextToLine(LatestLine, ListView.Items[i].Caption);
      for j := 0 to ListView.Items[i].SubItems.Count-1 do
      begin
        AddTextToLine(LatestLine, ListView.Items[i].SubItems[j]);
      end;
      MoveCompletedLineToList(Strings, LatestLine);
    end;
    Strings.SaveToFile(FileName, TEncoding.UTF8);
  finally
    Strings.Free;
  end;
end;

procedure ListViewLoadFromFile(ListView: TListView; const FileName: string);
var
  Strings: TStringList;
  i, j: Integer;
  Fields: TStringDynArray;
  Item: TListItem;
begin
  Strings := TStringList.Create;
  try
    Strings.LoadFromFile(FileName);
    ListView.Clear;
    for i := 0 to Strings.Count-1 do
    begin
      Fields := SplitString(Strings[i], #9);
      Item := ListView.Items.Add;
      Item.Caption := Fields[0];
      for j := 1 to high(Fields) do
      begin
        Item.SubItems.Add(Fields[j]);
      end;
    end;
  finally
    Strings.Free;
  end;
end;

Son olarak, programdan çıkıldığına yapılan değişikliklerin kaydedilip kaydedilmeyeceğini sormamız lazım. Bunun için Form1'in Close olayını şu şekilde kullanıyoruz:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  If Application.MessageBox('Yapılan değişiklikler kaydedilsin mi?', '', MB_YESNO+MB_ICONQUESTION+MB_DEFBUTTON1+MB_APPLMODAL) = ID_YES Then
    ListViewSaveToFile(lv1,GecerliKlasoruAl+'lv.txt');
end;

 

21.01.2017 12:05:01

Yorumlar

merhaba, 29.satırda bulunan ListViewLoadFromFile satırının altını aynı burada olduğu gibi kırmızı çizgiyi çizdi, oraya kadar tamam ama burada takıldım.

Gokhan Murat Bürge, 13.02.2023 13:49:31


Yazı hakkında yorum yapmak için, buraya tıklayın.

Kategoriler :

Arşiv :

Etiketler :

Bağlantılar :