Skip to content

7. C# ve VS.NET ile Grafik Arayüzler

7.1. Grafik kullanıcı arayüzlerinin temelleri

7.1.1. İlk proje

"Windows Uygulaması" türünde ilk projemizi oluşturalım:

  • [1]: yeni bir proje oluşturma
  • [2]: Windows Uygulaması türü
  • [3]: Şu an için projenin adı önemli değil
  • [4]: proje oluşturuldu
  • [5]: mevcut çözümü kaydediyoruz
  • [6]: proje adı
  • [7]: çözüm klasörü
  • [8]: çözüm adı
  • [9]: [Chap5] çözümüne ait bir klasör oluşturulacak. Bu çözümün projeleri alt klasörlerde yer alacaktır.
  • [10]: [Chap5] çözümündeki [01] projesi:
  • [Program.cs], projenin ana sınıfıdır
  • [Form1.cs], pencerenin davranışını yönetecek kaynak dosyadır [11]
  • [Form1.Designer.cs], [11] penceresinin bileşenlerine ilişkin bilgileri kapsülleyecek kaynak dosyadır
  • [11]: "tasarım" (design) modundaki [Form1.cs] dosyası
  • [12]: Oluşturulan uygulama (Ctrl-F5) tuşlarıyla çalıştırılabilir. [Form1] penceresi görüntülenir. Bu pencereyi taşıyabilir, boyutunu değiştirebilir ve kapatabilirsiniz. Böylece, bir grafik penceresinin temel öğelerine sahip olursunuz.

Ana sınıf [Program.cs] şu şekildedir:


using System;
using System.Windows.Forms;

namespace Chap5 {
    static class Program {
        /// <summary>
        /// Uygulamanın ana giriş noktası.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
  • 2. satır: Form içeren uygulamalar System.Windows.Forms ad alanını kullanır.
  • 4. satır: İlk ad alanı Chap5 olarak yeniden adlandırıldı.
  • 10. satır: Proje çalıştırıldığında (Ctrl-F5), [Main] yöntemi yürütülür.
  • 11-13. satırlar: Application sınıfı, System.Windows.Forms ad alanına aittir. Bu sınıf, Windows grafik uygulamalarını başlatmak ve durdurmak için statik yöntemler içerir.
  • 11. satır: isteğe bağlı - bir forma yerleştirilen denetimlere farklı görsel stiller atamaya olanak tanır
  • 12. satır: isteğe bağlı - denetimlerin metinlerinin görüntüleme motorunu belirler: GDI+ (true), GDI (false)
  • 13. satır: [Main] yönteminin tek zorunlu satırıdır: form sınıfı olan [Form1] sınıfını örneklendirir ve çalıştırılmasını ister.

[Form1.cs] kaynak dosyası şöyledir:


using System;
using System.Windows.Forms;

namespace Chap5 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }
    }
}
  • 5. satır: Form1 sınıfı, tüm pencerelerin ana sınıfı olan [System.Windows.Forms.Form] sınıfından türetilmiştir. "partial" anahtar sözcüğü, sınıfın kısmi olduğunu ve diğer kaynak dosyalarla tamamlanabileceğini belirtir. Burada da durum böyledir; Form1 sınıfı iki dosyaya bölünmüştür:
  • [Form1.cs]: Bu dosyada, özellikle olay işleyicileri olmak üzere formun davranışları bulunur
  • [Form1.Designer.cs]: Bu dosyada, form bileşenleri ve özellikleri bulunur. Bu dosyanın özelliği, kullanıcı [conception] modunda pencereyi her değiştirdiğinde yeniden oluşturulmasıdır.
  • 6-8. satırlar: Form1 sınıfının oluşturucusu
  • 7. satır: InitializeComponent yöntemini çağırır. Bu yöntemin [Form1.cs]'te bulunmadığı görülmektedir. Bu yöntem [Form1.Designer.cs]'te bulunur.

[Form1.Designer.cs] kaynak dosyası şu şekildedir:


namespace Chap5 {
    partial class Form1 {
        /// <summary>
        /// Gerekli tasarımcı değişkeni.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Kullanılan tüm kaynakları temizleyin.
        /// </summary>
        /// <param name="disposing">Yönetilen kaynakların imha edilmesi gerekiyorsa true; aksi takdirde false.</param>
        protected override void Dispose(bool disposing) {
            if (disposing && (components != null)) {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #Windows Form Designer tarafından oluşturulan kod bölümü

        /// <summary>
        /// Tasarımcı desteği için gerekli yöntem - değiştirmeyin
        /// bu yöntemin içeriğini kod düzenleyicisiyle değiştirmeyin.
        /// </summary>
        private void InitializeComponent() {
            this.SuspendLayout();
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(196, 98);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);

        }

         #endregion

    }
}
  • 2. satır: Bu yine Form1 sınıfıdır. Artık bu sınıfın Form sınıfından türediğinin tekrar edilmesine gerek olmadığına dikkat edilmelidir.
  • 25-37. satırlar: [Form1] sınıfının oluşturucusu tarafından çağrılan InitializeComponent yöntemi. Bu yöntem, formun tüm bileşenlerini oluşturacak ve başlatacaktır. Form, [conception] modunda her değiştirildiğinde bu yöntem yeniden oluşturulur. région adlı bir bölüm, 19-39. satırlar arasında bu alanı sınırlamak üzere oluşturulur. Geliştirici bu bölgeye kod eklememelidir: bir sonraki yeniden oluşturma işleminde bu kod üzerine yazılacaktır.

İlk etapta [Form1.Designer.cs] koduyla ilgilenmemek daha kolaydır. Bu kod otomatik olarak oluşturulur ve geliştiricinin [conception] modunda yaptığı seçimlerin C# diline çevirisidir. İlk örneği ele alalım:

  • [1]: [Form1.cs] dosyasına çift tıklayarak [conception] modunu seçin
  • [2]: Forma sağ tıklayın ve [Properties]'i seçin
  • [3]: [Form1]'in özellikler penceresi
  • [4]: [Text] özelliği pencerenin başlığını temsil eder
  • [5]: [Text] özelliğindeki değişiklik, [conception] modunda ve kaynak kodda da dikkate alınır [Form1.Designer.cs]:

        private void InitializeComponent() {
            this.SuspendLayout();
...
            this.Text = "Mon 1er formulaire";
...
}

7.1.2. İkinci bir proje

7.1.2.1. Form

02 adlı yeni bir projeye başlıyoruz. Bunun için, daha önce açıklanan proje oluşturma prosedürünü takip ediyoruz. Oluşturulacak pencere şöyledir:

Formun bileşenleri şunlardır:

No
ad
tür
rol
1
labelSaisie
Etiket
bir açıklama
2
textBoxSaisie
TextBox
giriş alanı
3
buttonAfficher
Düğme
giriş alanının içeriğini bir iletişim kutusunda görüntülemek için textBoxSaisie

Bu pencereyi oluşturmak için aşağıdaki adımları uygulayabilirsiniz:

  • [1]: Form üzerinde herhangi bir bileşenin dışında sağ tıklayın ve [Properties] seçeneğini seçin
  • [2]: Pencerenin özellikler sayfası, Visual Studio'nun sağ alt köşesinde görünür

Formun dikkat edilmesi gereken özellikleri arasında şunlar yer alır:

BackColor
pencerenin arka plan rengini ayarlamak için
ForeColor
penceredeki çizimlerin veya metnin rengini ayarlamak için
Menu
pencereye bir menü eklemek için
Text
pencereye bir başlık vermek için
FormBorderStyle
pencere türünü belirlemek için
Font
penceredeki yazıların yazı tipini ayarlamak için
Name
pencerenin adını ayarlamak için

Burada, Text ve Name özelliklerini ayarlıyoruz:

Text
Girişler ve düğmeler - 1
Name
frmSaisiesBoutons
  • [1]: Visual Studio tarafından sunulan araç kutuları arasından [Common Controls] araç kutusunu seçin
  • [2, 3, 4]: [Label], [Button] ve [TextBox] bileşenlerine art arda çift tıklayın
  • [5]: Üç bileşen de formun üzerindedir

Bileşenleri doğru şekilde hizalamak ve boyutlandırmak için araç çubuğundaki öğeleri kullanabilirsiniz:

 
  
   

Biçimlendirme ilkesi şöyledir:

  1. birlikte biçimlendirilecek farklı bileşenleri seçin (bileşenleri seçerken Ctrl tuşunu basılı tutun)
  2. istediğiniz biçimlendirme türünü seçin:
  • (devamı)
    • Align seçenekleri, bileşenleri üstten, alttan, sol veya sağdan ya da ortadan hizalamaya olanak tanır
    • Make Same Size seçenekleri, bileşenlerin aynı yüksekliğe veya genişliğe sahip olmasını sağlar
    • Horizontal Spacing seçeneği, bileşenleri aralarında eşit genişlikte boşluklar bırakarak yatay olarak hizalamaya olanak tanır. Aynı şekilde, Vertical Spacing seçeneği de bileşenleri dikey olarak hizalamaya olanak tanır.
    • Center seçeneği, bir bileşeni pencerede yatay olarak (Horizontally) veya dikey olarak (Vertically) ortalamaya olanak tanır

Bileşenleri yerleştirdikten sonra özelliklerini belirleriz. Bunun için bileşene sağ tıklayıp Properties seçeneğini seçin:

  • [1]: bileşeni seçerek özellikler penceresini açın. Bu pencerede aşağıdaki özellikleri değiştirin: name: labelSaisie, text: Saisie
  • [2]: Aynı şekilde devam edin: name: textBoxSaisie, text: hiçbir şey girmeyin
  • [3]: name: buttonAfficher, text: Afficher
  • [4]: pencerenin kendisi: ad: frmSaisiesBoutons, metin: Girişler ve düğmeler - 1
  • [5]: Projeyi çalıştırın (Ctrl-F5) ve pencerenin çalışır halini ilk kez önizleyin.

[conception] modunda yapılanlar, [Form1.Designer.cs] koduna aktarıldı:


namespace Chap5 {
    partial class frmSaisiesBoutons {
...
        private System.ComponentModel.IContainer components = null;
...
        private void InitializeComponent() {
            this.labelSaisie = new System.Windows.Forms.Label();
            this.buttonAfficher = new System.Windows.Forms.Button();
            this.textBoxSaisie = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            // 
            // labelSaisie
            // 
            this.labelSaisie.AutoSize = true;
            this.labelSaisie.Location = new System.Drawing.Point(12, 19);
            this.labelSaisie.Name = "labelSaisie";
            this.labelSaisie.Size = new System.Drawing.Size(35, 13);
            this.labelSaisie.TabIndex = 0;
            this.labelSaisie.Text = "Saisie";
            // 
            // buttonAfficher
            // 
            this.buttonAfficher.Location = new System.Drawing.Point(80, 49);
            this.buttonAfficher.Name = "buttonAfficher";
            this.buttonAfficher.Size = new System.Drawing.Size(75, 23);
            this.buttonAfficher.TabIndex = 1;
            this.buttonAfficher.Text = "Afficher";
            this.buttonAfficher.UseVisualStyleBackColor = true;
            this.buttonAfficher.Click += new System.EventHandler(this.buttonAfficher_Click);
            // 
            // textBoxSaisie
            // 
            this.textBoxSaisie.Location = new System.Drawing.Point(80, 19);
            this.textBoxSaisie.Name = "textBoxSaisie";
            this.textBoxSaisie.Size = new System.Drawing.Size(100, 20);
            this.textBoxSaisie.TabIndex = 2;
            // 
            // frmSaisiesBoutons
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(292, 118);
            this.Controls.Add(this.textBoxSaisie);
            this.Controls.Add(this.buttonAfficher);
            this.Controls.Add(this.labelSaisie);
            this.Name = "frmSaisiesBoutons";
            this.Text = "Saisies et boutons - 1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        private System.Windows.Forms.Label labelSaisie;
        private System.Windows.Forms.Button buttonAfficher;
        private System.Windows.Forms.TextBox textBoxSaisie;

    }
}
  • 53-55. satırlar: Üç bileşen, [Form1] sınıfında üç özel alan oluşturmuştur. Bu alanların adlarının, [conception] modunda bileşenlere verilen adlar olduğu dikkatinizi çekecektir. Aynı durum, 2. satırdaki form için de geçerlidir; bu, sınıfın kendisidir.
  • satır 7-9: [Label], [TextBox] ve [Button] türündeki üç nesne oluşturulur. Görsel bileşenler bu nesneler aracılığıyla yönetilir.
  • 14-19. satırlar: labelSaisie etiketinin yapılandırılması
  • 23-29. satırlar: buttonAfficher düğmesinin yapılandırılması
  • satır 33-36: textBoxSaisie giriş alanının yapılandırılması
  • 40-47. satırlar: frmSaisiesBoutons formunun yapılandırılması. 43-45. satırlarda, forma bileşenlerin nasıl eklendiğine dikkat edilebilir.

Bu kod anlaşılırdır. Böylece, [conception] modunu kullanmadan kod yoluyla formlar oluşturulabilir. Visual Studio'nun MSDN belgelerinde bununla ilgili birçok örnek verilmiştir. Bu kodu iyi bir şekilde öğrenmek, çalışma zamanı sırasında formlar oluşturmanıza olanak tanır: örneğin, bir veritabanı tablosunun güncellenmesine izin veren bir formu anında oluşturabilirsiniz; bu tablonun yapısı ancak çalışma zamanında belirlenir.

Geriye, Afficher düğmesine tıklama olayını işleyen yordamı yazmak kalıyor. Düğmeyi seçerek özellikler penceresine erişin. Bu pencerede birkaç sekme bulunur:

  • [1]: alfabetik sırayla özellik listesi
  • [2]: denetimle ilgili olaylar

Bir denetimin özelliklerine ve olaylarına kategorilere göre veya alfabetik sırayla erişilebilir:

  • [3]: Kategorilere göre özellikler veya olaylar
  • [4]: Alfabetik sıraya göre özellikler veya olaylar

Catégories modundaki Events sekmesi, buttonAfficher düğmesi için şu şekildedir:

  • [1]: Pencerenin sol sütununda, düğme üzerinde gerçekleşebilecek olası olaylar listelenir. Bir düğmeye tıklanması, Click olayına karşılık gelir.
  • [2]: Sağ sütun, ilgili olay gerçekleştiğinde çağrılan yordamın adını içerir.
  • [3]: Click olayının hücresine çift tıklandığında, otomatik olarak kod penceresine geçilir ve Click olay işleyicisi yazılır; buttonAfficher düğmesi üzerinde:

using System;
using System.Windows.Forms;

namespace Chap5 {
    public partial class frmSaisiesBoutons : Form {
        public frmSaisiesBoutons() {
            InitializeComponent();
        }

        private void buttonAfficher_Click(object sender, EventArgs e) {

        }
    }
}
  • 10-12. satırlar: Click olayının, buttonAfficher adlı düğme için olay işleyicisinin iskeleti. Aşağıdaki noktalara dikkat edilmelidir:
    • yöntemin adı nomDuComposant_NomEvénement şemasına göre belirlenmiştir
    • Yöntem özel niteliktedir. İki parametre alır:
    • sender: Olayı tetikleyen nesnedir. Yordam, buttonAfficher düğmesine tıklanmasının ardından yürütülürse, sender değeri buttonAfficher'e eşit olacaktır. buttonAfficher_Click yordamının başka bir yordamdan çalıştırıldığını varsayabiliriz. Bu durumda, söz konusu yordam ilk parametre olarak istediği sender nesnesini serbestçe belirleyebilir.
    • EventArgs: olayla ilgili bilgileri içeren bir nesne. Click olayında bu nesne boş olur. Fare hareketleriyle ilgili bir olayda ise farenin (X, Y) koordinatları bulunur.
    • Burada bu parametrelerin hiçbirini kullanmayacağız.

Bir olay işleyicisi yazmak, önceki kod iskeletini tamamlamaktan ibarettir. Burada, içinde textBoxSaisie alanının içeriği (boş değilse) veya aksi takdirde bir hata mesajı ([2]) bulunan bir iletişim kutusu görüntülemek istiyoruz:

Bunu gerçekleştiren kod şu şekilde olabilir:


        private void buttonAfficher_Click(object sender, EventArgs e) {
            // TextBox'e girilen metin görüntülenir textboxSaisie
            string texte = textBoxSaisie.Text.Trim();
            if (texte.Length != 0) {
                MessageBox.Show("Texte saisi= " + texte, "Vérification de la saisie", MessageBoxButtons.OK, MessageBoxIcon.Information);
            } else {
                MessageBox.Show("Saissez un texte...", "Vérification de la saisie", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

MessageBox sınıfı, bir pencerede mesajları görüntülemek için kullanılır. Burada şu Show yöntemini kullandık:


public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon);

ile

text
görüntülenecek mesaj
caption
pencerenin başlığı
buttons
pencerede bulunan düğmeler
icon
pencerede bulunan simge

buttons parametresi, yukarıda 7. satırda gösterildiği gibi (MessageBoxButtons ön ekiyle) aşağıdaki sabitlerden bir değer alabilir:

constante
düğmeler
   AbortRetryIgnore 
  OK 
    OKCancel 
    RetryCancel 
    YesNo 
    YesNoCancel 

icon parametresi, yukarıda (10. satırda gösterildiği gibi MessageBoxIcon ön ekiyle) belirtilen sabitler arasından değer alabilir:

Asterisk
Error
aynı Stop
Exclamation
aynı Uyarı
Hand
Information
Aynı şekilde Asterisk
None
Question
Stop
aynı şekilde El
Warning

 

Show yöntemi, bir sıralama olan [System.Windows.Forms.DialogResult] türünde bir sonuç döndüren statik bir yöntemdir:

Image

Kullanıcının MessageBox türündeki pencereyi kapatmak için hangi düğmeye bastığını öğrenmek için şunu yazacağız:

DialogResult res=MessageBox.Show(..);
if (res==DialogResult.Yes){ // "Evet" düğmesine bastı...}

7.1.2.2. Olay yönetimi ile ilgili kod

Yazdığımız buttonAfficher_Click işlevinin yanı sıra, Visual Studio, form bileşenlerini oluşturan ve başlatan [Form1.Designer.cs]'in InitializeComponents yönteminde şu satırı oluşturmuştur:


            this.buttonAfficher.Click += new System.EventHandler(this.buttonAfficher_Click);

Click, Button ve [1, 2, 3] sınıflarının bir olaydır:

  • [5]: [Control.Click] ve [4] olaylarının tanımlanması. Böylece, Click olayının [Button] sınıfına özgü olmadığı görülmektedir. Bu olay, [Button] sınıfının üst sınıfı olan [Control] sınıfına aittir.
    • EventHandler, delegate olarak adlandırılan bir yöntem prototipidir (modeldir). Buna daha sonra tekrar döneceğiz.
    • event, delegate ve EventHandler sınıflarının işlevlerini kısıtlayan bir anahtar kelimedir: Bir delegate nesnesi, bir event nesnesinden daha zengin işlevlere sahiptir.

delegate ve EventHandler şu şekilde tanımlanmıştır:

 

delegate ve EventHandler, bir yöntem şablonunu ifade eder:

  • 1. parametresi Object türü olan
  • 2. parametresi EventArgs türündedir
  • hiçbir sonuç döndürmez

Bu, Visual Studio tarafından oluşturulan buttonAfficher düğmesine tıklama işleme yönteminde olduğu gibidir:


        private void buttonAfficher_Click(object sender, EventArgs e);

Dolayısıyla, buttonAfficher_Click yöntemi, EventHandler türü tarafından tanımlanan prototipe karşılık gelir. EventHandler türünde bir nesne oluşturmak için aşağıdaki adımlar izlenir:

EventHandler evtHandler=new EventHandler(méthode correspondant au prototype  défini par le type EventHandler);

buttonAfficher_Click yöntemi, EventHandler türü tarafından tanımlanan prototipe karşılık geldiğinden, şu şekilde yazılabilir:

EventHandler evtHandler=new EventHandler(buttonAfficher_Click);

delegate türündeki bir değişken, aslında delegate türündeki yöntemlere ilişkin bir referans listesidir. Yukarıdaki evtHandler değişkenine yeni bir M yöntemi eklemek için şu sözdizimini kullanacağız:

evtHandler+=new EvtHandler(M);

evtHandler boş bir liste olsa bile += notasyonu kullanılabilir.

[InitializeComponent] satırına geri dönelim; bu satır, buttonAfficher nesnesinin Click olayına bir olay işleyicisi ekler:


            this.buttonAfficher.Click += new System.EventHandler(this.buttonAfficher_Click);

Bu komut, EventHandler türünde bir yöntemi buttonAfficher.Click alanının yöntem listesine ekler. Bu yöntemler, buttonAfficher bileşenindeki Click olayı her algılandığında çağrılacaktır. Genellikle sadece bir tane vardır. Buna "olay işleyicisi" denir.

EventHandler'in imzasına geri dönelim:


        private delegate void EventHandler(object sender, EventArgs e);

delegate'in ikinci parametresi, EventArgs türünde veya bu sınıftan türetilmiş bir nesnedir. EventArgs türü çok geneldir ve aslında meydana gelen olay hakkında hiçbir bilgi vermez. Bir düğmeye tıklama için bu yeterlidir. Bir form üzerinde fare hareketi için ise, şu şekilde tanımlanan [Form] sınıfından bir MouseMove olayı olur:

public event MouseEventHandler MouseMove;

delegate ve MouseEventHandler şu şekilde tanımlanmıştır:

 

Bu, void f (object, MouseEventArgs) imzasına sahip bir delege işlevidir. MouseEventArgs sınıfı ise şu şekilde tanımlanmıştır:

MouseEventArgs sınıfı, EventArgs sınıfından daha zengin özelliklere sahiptir. Örneğin, olayın meydana geldiği anda farenin X ve Y koordinatlarını öğrenebiliriz.

7.1.2.3. Conclusion

İncelenen iki projeden, Visual Studio ile grafik arayüz oluşturulduktan sonra, geliştiricinin işinin esas olarak bu grafik arayüz için yönetmek istediği olay işleyicilerini yazmaktan ibaret olduğu sonucuna varabiliriz. Kod, Visual Studio tarafından otomatik olarak üretilir. Karmaşık olabilen bu kod, ilk aşamada göz ardı edilebilir. Daha sonra bu kodun incelenmesi, formların oluşturulması ve yönetilmesini daha iyi anlamaya yardımcı olabilir.

7.2. Temel bileşenler

Şimdi, en yaygın bileşenleri kullanan çeşitli uygulamaları sunarak, bu bileşenlerin temel yöntem ve özelliklerini keşfedeceğiz. Her uygulama için, grafik kullanıcı arayüzünü ve ilgili kodu, özellikle de olay işleyicilerin kodunu sunacağız.

7.2.1. Form Formu

Öncelikle, bileşenlerin yerleştirildiği vazgeçilmez bileşen olan formu tanıtacağız. Bu bileşenin temel özelliklerinden bazılarını daha önce ele almıştık. Burada, bir formdaki bazı önemli olaylar üzerinde duracağız.

Load
form yükleniyor
Closing
Form kapatılıyor
Closed
form kapatıldı

Load olayı, form görüntülenmeden önce gerçekleşir. Closing olayı ise form kapanırken gerçekleşir. Bu kapanma işlemi, programlama yoluyla durdurulabilir.

Form1 adlı, bileşen içermeyen bir form oluşturuyoruz:

  • [1]: form
  • [2]: işlenen üç olay

[Form1.cs] kodunun içeriği şöyledir:


using System;
using System.Windows.Forms;

namespace Chap5 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            // formun ilk yüklemesi
            MessageBox.Show("Evt Load", "Load");
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            // form kapanıyor
            MessageBox.Show("Evt FormClosing", "FormClosing");
            // onay isteniyor
            DialogResult réponse = MessageBox.Show("Voulez-vous vraiment quitter l'application", "Closing", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (réponse == DialogResult.No)
                e.Cancel = true;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
            // form kapatılmak üzere
            MessageBox.Show("Evt FormClosed", "FormClosed");
        }
    }
}

Çeşitli olaylardan haberdar olmak için MessageBox işlevini kullanıyoruz.

10. satır: Load olayı,
uygulama başlatıldığında, form görüntülenmeden önce gerçekleşecektir:
  
15. satır: FormClosing olayı,
kullanıcı pencereyi kapattığında gerçekleşecektir.
19. satır: Ardından, kullanıcıya uygulamadan gerçekten çıkmak isteyip istemediğini sorarız
:
satır 20: Hayır cevabı verirse, yöntemin aldığı
CancelEventArgs olayının, yöntemin
parametre olarak aldığı CancelEventArgs olayının Cancel özelliğini ayarlıyoruz. Bu özelliği False olarak ayarlarsak,
işlemi iptal edilir, aksi takdirde devam eder.
FormClosed olayı gerçekleşecektir:

7.2.2. Etiketler ve giriş kutuları TextBox

Bu iki bileşene daha önce rastlamıştık. Label bir metin bileşenidir ve TextBox bir giriş alanı bileşenidir. Bunların ana özelliği, giriş alanının içeriğini ya da etiket metnini belirten Text'tir. Bu özellik okuma/yazma erişimine sahiptir.

TextBox için genellikle kullanılan olay, kullanıcının giriş alanını değiştirdiğini bildiren TextChanged'tir. Aşağıda, bir giriş alanındaki değişiklikleri takip etmek için TextChanged olayını kullanan bir örnek verilmiştir:

no
tür
ad
rol
1
TextBox
textBoxSaisie
giriş alanı
2
Etiket
labelControle
1'deki metni gerçek zamanlı olarak görüntüler
AutoSize=False, Text=(hiçbir şey)
3
Düğme
buttonEffacer
1 ve 2 numaralı alanları silmek için
4
Düğme
buttonQuitter
uygulamadan çıkmak için

Bu uygulamanın kodu şöyledir:


using System.Windows.Forms;

namespace Chap5 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void textBoxSaisie_TextChanged(object sender, System.EventArgs e) {
            // TextBox'in içeriği değişti - labelControle etiketine kopyalanıyor
            labelControle.Text = textBoxSaisie.Text;
        }

        private void buttonEffacer_Click(object sender, System.EventArgs e) {
            // giriş kutusunun içeriği siliniyor
            textBoxSaisie.Text = "";
        }

        private void buttonQuitter_Click(object sender, System.EventArgs e) {
            // Çıkış düğmesine tıklanıyor - uygulamadan çıkılıyor
            Application.Exit();
        }

        private void Form1_Shown(object sender, System.EventArgs e) {
            // giriş alanına odaklanıyoruz
            textBoxSaisie.Focus();
        }
    }
}
  • 24. satır: [Form].Shown olayı, form görüntülendiğinde gerçekleşir
  • 26. satır: Ardından, textBoxSaisie bileşenine (giriş yapmak için) odak verilir.
  • 9. satır: [TextBox].TextChanged olayı, TextBox bileşeninin içeriği her değiştiğinde gerçekleşir
  • 11. satır: [TextBox] bileşeninin içeriği, [Label] bileşenine kopyalanır
  • 14. satır: [Effacer] düğmesine yapılan tıklamayı yönetir
  • 16. satır: [TextBox] bileşenine boş bir dize eklenir
  • 19. satır: [Quitter] düğmesine tıklamayı yönetir
  • 21. satır: Çalışmakta olan uygulamayı durdurmak için. Application nesnesinin, [Form1.cs]'in [Main] yönteminde uygulamayı başlatmak için kullanıldığını hatırlayalım:

        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
}

Aşağıdaki örnekte çok satırlı bir TextBox kullanılmaktadır:

Kontrol listesi şöyledir:

No
tür
ad
rol
1
TextBox
textBoxLignes
çok satırlı giriş alanı
Multiline=true, ScrollBars=Both, AcceptReturn=True, AcceptTab=True
2
TextBox
textBoxLigne
tek satırlık giriş alanı
3
Düğme
buttonAjouter
2'den 1'e içerik ekler

Bir TextBox'in çok satırlı hale gelmesi için kontrolün aşağıdaki özellikleri ayarlanır:

Multiline=true
birden fazla satır metin kabul etmek için
ScrollBars=( None, Horizontal, Vertical, Both)
kontrolün kaydırma çubuklarına sahip olmasını (Yatay, Dikey, Her İkisi) veya sahip olmamasını (Yok) belirlemek için
AcceptReturn=(True, False)
true olarak ayarlandığında, Enter tuşu satır sonu işlevi görür
AcceptTab=(True, False)
true değerine ayarlandığında, Tab tuşu metinde bir sekme oluşturur

Uygulama, satırları doğrudan [1]'e yazmanıza veya [2] ve [3] aracılığıyla eklemenize olanak tanır.

Uygulamanın kodu şöyledir:


using System.Windows.Forms;
using System;

namespace Chap5 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        private void buttonAjouter_Click(object sender, System.EventArgs e) {
            // textBoxLigne'in içeriği, textBoxLignes'in içeriğine eklenir
            textBoxLignes.Text += textBoxLigne.Text+Environment.NewLine;
            textBoxLigne.Text = "";
        }

        private void Form1_Shown(object sender, EventArgs e) {
            // giriş alanına odaklanılır
            textBoxLigne.Focus();
        }
    }
}
  • 18. satır: Form görüntülendiğinde (muhtemelen Shown), textBoxLigne giriş alanına odak verilir
  • 10. satır: [Ajouter] düğmesine yapılan tıklamayı yönetir
  • 12. satır: textBoxLigne giriş alanındaki metin, textBoxLignes giriş alanındaki metne eklenir ve ardından bir satır atlaması yapılır.
  • 13. satır: textBoxLigne giriş alanı silinir

7.2.3. Açılır listeler ComboBox

Aşağıdaki formu oluşturuyoruz:

no
tür
ad
rol
1
ComboBox
comboNombres
şu karakter dizilerini içerir
DropDownStyle=DropDownList

Bir ComboBox bileşeni, bir giriş alanı ile birlikte açılır bir listedir: kullanıcı ya (2) içinden bir öğe seçebilir ya da (1) içine metin girebilir. DropDownStyle özelliği tarafından belirlenen üç tür ComboBox vardır:

Simple
açılır liste içermeyen, düzenleme alanı bulunan liste
DropDown
düzenleme alanı içeren açılır liste
DropDownList
düzenleme alanı olmayan açılır liste

Varsayılan olarak, bir ComboBox nesnesinin türü DropDown'tir.

ComboBox sınıfının tek bir oluşturucusu vardır:

new ComboBox()
boş bir açılır liste oluşturur

ComboBox öğeleri, Items özelliğinde bulunur:

public ComboBox.ObjectCollection Items {get;}

Bu, indeksli bir özelliktir; Items[i], açılır menünün i numaralı öğesini belirtir. Bu özellik salt okunurdur.

C bir açılır menü ve C.Items ise öğe listesi olsun. Aşağıdaki özellikler mevcuttur:

C.Items.Count
Combo'daki öğe sayısı
C.Items[i]
kombinasyon menüsünün i numaralı öğesi
C.Add(object o)
o nesnesini kombinasyonun son öğesi olarak ekler
C.AddRange(object[] objets)
kombinasyonun sonuna bir nesne tablosu ekler
C.Insert(int i, object o)
o nesnesini kombo menüsünün i konumuna ekler
C.RemoveAt(int i)
kombinasyon menüsünden i numaralı öğeyi kaldırır
C.Remove(object o)
o nesnesini kombo listesinden kaldır
C.Clear()
kombinasyondaki tüm öğeleri sil
C.IndexOf(object o)
o nesnesini açılır menüdeki i konumuna getirir
C.SelectedIndex
seçilen öğenin dizini
C.SelectedItem
seçilen öğe
C.SelectedItem.Text
seçilen öğenin görüntülenen metni
C.Text
seçili öğenin görüntülenen metni

Bir açılır menünün görsel olarak karakter dizileri gösterirken nesneler içerebilmesi şaşırtıcı gelebilir. Bir ComboBox, obj nesnesini içeriyorsa, obj.ToString() dizesini görüntüler. Hatırlanacağı üzere, her nesne, object sınıfından miras alınan ve nesneyi "temsil eden" bir karakter dizisi döndüren ToString yöntemine sahiptir.

C açılır menüsünden seçilen Item öğesi, C.SelectedItem veya C.Items[C.SelectedIndex] şeklindedir; burada C.SelectedIndex, ve bu numara ilk öğe için sıfırdan başlar. Seçilen metin çeşitli şekillerde elde edilebilir: C.SelectedItem.Text, C.Text

Açılır listeden bir öğe seçildiğinde SelectedIndexChanged olayı tetiklenir; bu olay, açılır listedeki seçim değişikliğinden haberdar olmak için kullanılabilir. Aşağıdaki uygulamada, bu olayı kullanarak listeden seçilen öğeyi görüntülüyoruz.

 

Uygulamanın kodu şöyledir:


using System.Windows.Forms;

namespace Chap5 {
    public partial class Form1 : Form {
        private int previousSelectedIndex=0;

        public Form1() {
            InitializeComponent();
            // açılır menü dolduruluyor
            comboBoxNombres.Items.AddRange(new string[] { "zéro", "un", "deux", "trois", "quatre" });
            // 0 numaralı öğe seçildi
            comboBoxNombres.SelectedIndex = 0;
        }

        private void comboBoxNombres_SelectedIndexChanged(object sender, System.EventArgs e) {
            int newSelectedIndex = comboBoxNombres.SelectedIndex;
            if (newSelectedIndex != previousSelectedIndex) {
                // seçilen öğe değişti - görüntülenir
                MessageBox.Show(string.Format("Elément sélectionné : ({0},{1})", comboBoxNombres.Text, newSelectedIndex), "Combo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                // yeni indeksi kaydedilir
                previousSelectedIndex = newSelectedIndex;
            }
        }
    }
}
  • 5. satır: previousSelectedIndex, açılır menüde en son seçilen indeksi kaydeder
  • 10. satır: açılır menü, bir karakter dizisi tablosuyla doldurulur
  • 12. satır: İlk öğe seçilir
  • 15. satır: Kullanıcı açılır menüden bir öğe seçtiğinde her seferinde yürütülen yöntem. Olayın adının aksine, seçilen öğe bir öncekiyle aynı olsa bile bu olay gerçekleşir.
  • satır 16: Seçilen öğenin indeksi kaydedilir
  • 17. satır: Eğer bir öncekinden farklıysa
  • 19. satır: Seçilen öğenin numarası ve metni görüntülenir
  • 21. satır: yeni indeksi kaydedilir

7.2.4. ListBox Bileşeni

Aşağıdaki arayüzü oluşturmayı planlıyoruz:

Bu pencerenin bileşenleri şunlardır:

No
tür
ad
rol/özellikler
0
Form
Form1
form
FormBorderStyle=FixedSingle (boyutu değiştirilemeyen çerçeve)
1
TextBox
textBoxSaisie
giriş alanı
2
Düğme
buttonAjouter
[1] giriş alanının içeriğini [3] listesine eklemeye yarayan düğme
3
ListBox
listBox1
Liste 1
SelectionMode=MultiExtended :
4
ListBox
listBox2
Liste 2
SelectionMode=MultiSimple :
5
Düğme
button1vers2
seçilen öğeleri liste 1'den liste 2'ye aktarır
6
Düğme
button2vers1
tersi işlemi yapar
7
Düğme
buttonEffacer1
listeyi boşalt 1
8
Düğme
buttonEffacer2
Liste 2'yi boşalt

ListBox bileşenlerinin öğe seçim modu, SelectionMode özelliği ile tanımlanır:

One
yalnızca tek bir öğe seçilebilir
MultiExtended
çoklu seçim mümkündür: SHIFT tuşunu basılı tutarak bir öğeye tıklandığında, seçim önceki öğeden mevcut öğeye genişletilir.
MultiSimple
çoklu seçim mümkündür: bir öğe, fareyle tıklanarak veya boşluk tuşuna basılarak seçilir/seçimi kaldırılır.
  • Kullanıcı, alan 1'e metin girer. Ajouter (2) düğmesiyle bunu liste 1'e ekler. Giriş alanı (1) bu durumda boşaltılır ve kullanıcı yeni bir öğe ekleyebilir.
  • Kullanıcı, bir listeden diğerine öğeleri aktarabilir; bunun için aktarılacak öğeyi listelerden birinde seçip uygun aktarım düğmesi 5 veya 6'yı seçer. Aktarılan öğe, hedef listenin sonuna eklenir ve kaynak listeden kaldırılır.
  • Kullanıcı, Liste 1'deki bir öğeye çift tıklayabilir. Bu durumda söz konusu öğe, düzenleme amacıyla giriş kutusuna aktarılır ve Liste 1'den kaldırılır.

Düğmeler aşağıdaki kurallara göre yanar veya söner:

  • Ajouter düğmesi, yalnızca giriş alanında boş olmayan bir metin varsa yanar
  • Liste 1'den Liste 2'ye aktarım düğmesi [5], yalnızca Liste 1'de seçili bir öğe varsa yanar
  • Liste 2'den Liste 1'e aktarım düğmesi ([6]), yalnızca Liste 2'de seçili bir öğe varsa yanar
  • Liste 1 ve Liste 2'yi silme düğmeleri [7] ve [8], yalnızca silinecek listede öğeler varsa yanar.

Yukarıdaki koşullarda, uygulama başlatıldığında tüm düğmelerin kapalı olması gerekir. Bu durumda, düğmelerin Enabled özelliğini false olarak ayarlamak gerekir. Bunu tasarım aşamasında yapabiliriz; bu durumda InitializeComponent yönteminde ilgili kod otomatik olarak oluşturulur. Alternatif olarak, aşağıda gösterildiği gibi oluşturucuda kendimiz de yapabiliriz:


        public Form1() {
            InitializeComponent();
            // --- ek başlatmalar ---
            // bazı düğmeler devre dışı bırakılıyor
            buttonAjouter.Enabled = false;
            button1vers2.Enabled = false;
            button2vers1.Enabled = false;
            buttonEffacer1.Enabled = false;
            buttonEffacer2.Enabled = false;
}

Ajouter düğmesinin durumu, giriş alanının içeriği tarafından kontrol edilir. Bu içeriğindeki değişiklikleri takip etmemizi sağlayan olay TextChanged'tir:


        private void textBoxSaisie_TextChanged(object sender, System.EventArgs e) {
            // textBoxSaisie öğesinin içeriği değişti
            // "Ekle" düğmesi yalnızca giriş alanı boş değilse etkinleştirilir
            buttonAjouter.Enabled = textBoxSaisie.Text.Trim() != "";
        }

Aktarım düğmelerinin durumu, kontrol ettikleri listeden bir öğenin seçilip seçilmediğine bağlıdır:


        private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e) {
            // bir öğe seçildi
            // 1'den 2'ye aktarım düğmesi etkinleştirilir
            button1vers2.Enabled = true;
        }

        private void listBox2_SelectedIndexChanged(object sender, System.EventArgs e) {
            // bir öğe seçildi
            // 2'den 1'e aktarım düğmesi etkinleştirilir
            button2vers1.Enabled = true;
}

Ajouter düğmesine tıklanmasıyla ilişkili kod şöyledir:


        private void buttonAjouter_Click(object sender, System.EventArgs e) {
            // Liste 1'e yeni bir öğe eklendi
            listBox1.Items.Add(textBoxSaisie.Text.Trim());
            // giriş siliniyor
            textBoxSaisie.Text = "";
            // Liste 1 boş değil
            buttonEffacer1.Enabled = true;
            // odak giriş kutusuna geri dönüyor
            textBoxSaisie.Focus();
}

Formdaki bir denetime "odak" yerleştirmeye olanak tanıyan Focus yöntemine dikkat edilmelidir. Effacer düğmelerine tıklanmasıyla ilişkili kod:


        private void buttonEffacer1_Click(object sender, System.EventArgs e) {
            // Liste 1 siliniyor
            listBox1.Items.Clear();
            // Sil düğmesi
            buttonEffacer1.Enabled = false;
        }

        private void buttonEffacer2_Click(object sender, System.EventArgs e) {
            // Liste 2 siliniyor
            listBox2.Items.Clear();
            // Sil düğmesi
            buttonEffacer2.Enabled = false;
}

Seçilen öğeleri bir listeden diğerine aktaran kod:


        private void button1vers2_Click(object sender, System.EventArgs e) {
            // Liste 1'de seçilen öğeyi Liste 2'ye aktarma
            transfert(listBox1, button1vers2, buttonEffacer1, listBox2, button2vers1, buttonEffacer2);
        }

        private void button2vers1_Click(object sender, System.EventArgs e) {
            // Liste 2'de seçilen öğeyi Liste 1'e aktarma
            transfert(listBox2, button2vers1, buttonEffacer2, listBox1, button1vers2, buttonEffacer1);
        }

Yukarıdaki iki yöntem, bir listeden diğerine seçilen öğelerin aktarılmasını "transfer" adlı aynı özel yönteme devreder:


        // aktarım
        private void transfert(ListBox l1, Button button1vers2, Button buttonEffacer1, ListBox l2, Button button2vers1, Button buttonEffacer2) {
            // Liste l1'den seçilen öğelerin Liste l2'ye aktarılması
            for (int i = l1.SelectedIndices.Count - 1; i >= 0; i--) {
                // seçilen öğenin dizini
                int index = l1.SelectedIndices[i];
                // l2'ye ekleme
                l2.Items.Add(l1.Items[index]);
                // l1'den silme
                l1.Items.RemoveAt(index);
            }
            // Sil düğmeleri
            buttonEffacer2.Enabled = l2.Items.Count != 0;
            buttonEffacer1.Enabled = l1.Items.Count != 0;
            // aktarım düğmeleri
            button1vers2.Enabled = false;
}
  • satır b: "transfer" yöntemi altı parametre alır:
  • Seçilen öğeleri içeren ve burada l1 olarak adlandırılan listeye bir referans. Uygulama çalıştırıldığında, l1 ya listBox1 ya da listBox2 olur. buttonXversY_Click aktarım prosedürlerinin 3. ve 8. satırlarında çağrı örnekleri görülebilir.
  • l1 listesiyle bağlantılı aktarım düğmesine bir referans. Örneğin, l1 değeri listBox2 ise, bu button2vers1 olacaktır (bkz. 8. satırdaki çağrı)
  • l1 listesinin silme düğmesindeki referans. Örneğin, l1 listBox1 ise, bu buttonEffacer1 olacaktır (bkz. 3. satırdaki çağrı)
  • diğer üç referans da benzerdir ancak l2 listesine atıfta bulunur.
  • d satırı: [ListBox].SelectedIndices koleksiyonu, [ListBox] bileşeninde seçilen öğelerin indekslerini temsil eder. Bu bir koleksiyondur:
  • [ListBox].SelectedIndices.Count, bu koleksiyondaki öğe sayısını gösterir
  • [ListBox].SelectedIndices[i], bu koleksiyonun i numaralı elemanıdır

Koleksiyonu ters yönde inceleyeceğiz: koleksiyonun sonundan başlayıp başlangıcında bitireceğiz. Nedenini açıklayacağız.

  • f satırı: l1 listesinden seçilen bir öğenin indeksi
  • h satırı: bu eleman l2 listesine eklenir
  • j satırı: ve l1 listesinden silinir. Silindiği için artık seçili değildir. d satırındaki l1.SelectedIndices koleksiyonu yeniden hesaplanacaktır. Az önce silinen öğeyi kaybedecektir. Bundan sonraki tüm öğelerin numaraları n'den n-1'e düşecektir.
  • Eğer (d) satırındaki döngü artan bir sırayla ilerliyorsa ve az önce 0 numaralı öğeyi işlediyse, ardından 1 numaralı öğeyi işleyecektir. Ancak, 0 numaralı öğe silinmeden önce 1 numaralı olan öğe, bundan sonra 0 numara alacaktır. Dolayısıyla bu öğe döngü tarafından göz ardı edilecektir.
  • (d) satırındaki döngü azalan bir döngü ise ve n numaralı öğeyi işlediyse, bir sonraki adımda n-1 numaralı öğeyi işleyecektir. n numaralı öğenin silinmesinden sonra, n-1 numaralı öğenin numarası değişmez. Dolayısıyla bu öğe bir sonraki döngü turunda işlenir.
  • m-n satırları: [Effacer] düğmelerinin durumu, ilgili listelerde öğe olup olmamasına bağlıdır
  • p satırı: l2 listesinde artık seçili öğe kalmamıştır: aktarım düğmesi kapatılır.

7.2.5. CheckBox onay kutuları, ButtonRadio radyo düğmeleri

Aşağıdaki uygulamayı yazmayı planlıyoruz:

Pencerenin bileşenleri şunlardır:

No
tür
ad
işlev
1
GroupBox
bkz. [6]
groupBox1
bir bileşen konteyneri. Buraya başka bileşenler de eklenebilir.
Text=Radyo düğmeleri
2
RadioButton
radioButton1
radioButton2
radioButton3
3 radyo düğmesi - radioButton1, Checked=True ve Text=1 özelliklerine sahiptir - radioButton2, Text=2 özelliğine sahiptir - radioButton3, Text=3 özelliğine sahiptir
Aynı kapsayıcıda (burada GroupBox) bulunan radyo düğmeleri birbirini dışlar: bunlardan yalnızca biri seçili durumdadır.
3
GroupBox
groupBox2
 
4
CheckBox
checkBox1
checkBox2
checkBox3
3 onay kutusu. chechBox1, Checked=True ve Text=A özelliklerine sahiptir - chechBox2, Text=B özelliğine sahiptir - chechBox3, Text=C özelliğine sahiptir
5
ListBox
listBoxValeurs
bir değişiklik olduğu anda radyo düğmelerinin ve onay kutularının değerlerini gösteren bir liste.
6
  
GroupBox konteynerinin nerede olduğunu gösterir

Bu altı kontrol için bizi ilgilendiren olay, onay kutusunun veya radyo düğmesinin durumunun değiştiğini belirten CheckChanged olaydır. Bu durum, her iki durumda da Checked Boole özelliği ile temsil edilir; bu özelliğin değeri “true” ise, kontrolün işaretli olduğu anlamına gelir. Burada altı CheckChanged olayını işlemek için tek bir yöntem kullanacağız: affiche yöntemi. Altı CheckChanged olayının aynı affiche yöntemi tarafından yönetilmesini sağlamak için şu şekilde ilerleyebiliriz:

radioButton1 bileşenini seçin ve özelliklerine erişmek için üzerine sağ tıklayın:

événements [1] sekmesinde, affiche [2] yöntemini CheckChanged olayına atayalım. Bu, A1 seçeneğine yapılan tıklamanın affiche adlı bir yöntem tarafından işlenmesini istediğimiz anlamına gelir. Visual Studio, kod penceresinde affiche yöntemini otomatik olarak oluşturur:


private void affiche(object sender, EventArgs e) {
        }

affiche yöntemi, EventHandler türünde bir yöntemdir.

Diğer beş bileşen için de aynı işlem uygulanır. Örneğin, CheckBox1 seçeneğini ve buna ait [3] olaylarını seçelim. Click olayının karşısında, bu olayı işleyebilecek mevcut yöntemlerin bulunduğu bir [4] açılır listesi vardır. Burada sadece affiche. yöntemi bulunmaktadır; bunu seçin. Bu işlemi diğer tüm bileşenler için tekrarlayın.

InitializeComponent yönteminde kod oluşturulmuştur. affiche yöntemi, altı CheckedChanged olayının işleyicisi olarak şu şekilde tanımlanmıştır:


this.radioButton1.CheckedChanged += new System.EventHandler(this.affiche);
this.radioButton2.CheckedChanged += new System.EventHandler(this.affiche);
this.radioButton3.CheckedChanged += new System.EventHandler(this.affiche);
this.checkBox1.CheckedChanged += new System.EventHandler(this.affiche);
this.checkBox2.CheckedChanged += new System.EventHandler(this.affiche);
this.checkBox3.CheckedChanged += new System.EventHandler(this.affiche);

affiche yöntemi şu şekilde tamamlanmıştır:


        private void affiche(object sender, System.EventArgs e) {
            // radyo düğmesinin veya onay kutusunun durumunu gösterir
            // Bu bir onay kutusu mu?
            if (sender is CheckBox) {
                CheckBox chk = (CheckBox)sender;
                listBoxvaleurs.Items.Add(chk.Name + "=" + chk.Checked);
            }
            // Bu bir radyo düğmesi mi?
            if (sender is RadioButton) {
                RadioButton rdb = (RadioButton)sender;
                listBoxvaleurs.Items.Add(rdb.Name + "=" + rdb.Checked);
            }
}

Sözdizimi


            if (sender is CheckBox) {

, sender nesnesinin CheckBox türünde olduğunu doğrulamamızı sağlar. Bu sayede, sender'in tam türüne bir tür dönüştürme işlemi gerçekleştirebiliriz. affiche yöntemi, listBoxValeurs listesine olayı tetikleyen bileşenin adını ve Checked özelliğinin değerini yazar. [7] çalıştırıldığında, bir radyo düğmesine tıklanmasının iki CheckChanged olayı tetiklediği görülür: biri eski düğmede (işaretli durumdan "işaretsiz" duruma geçer) ve diğeri yeni düğmede (işaretsiz durumdan "işaretli" duruma geçer).

7.2.6. ScrollBar Değiştiriciler

Çeşitli tipte değişkenler mevcuttur:
yatay sürgülü (HscrollBar),
dikey değişken (VscrollBar),
artırıcı (NumericUpDown).

Şu uygulamayı gerçekleştirelim:

no
tür
ad
rol
1
hScrollBar
hScrollBar1
bir yatay frekans dönüştürücü
2
hScrollBar
hScrollBar2
1 numaralı sürücünün değişikliklerini takip eden bir yatay sürücü
3
Etiket
labelValeurHS1
yatay kaydırıcının değerini gösterir
4
NumericUpDown
numericUpDown2
2 numaralı kaydırıcının değerini sabitler

Bir ScrollBar kaydırıcı, kullanıcının, üzerinde bir imleç hareket eden kaydırıcının "şeridi" ile simgelenen tamsayı aralığından bir değer seçmesine olanak tanır. Kaydırıcının değeri, Value özelliğinde bulunur.

  • Yatay bir kaydırıcıda sol uç aralığın minimum değerini, sağ uç ise maksimum değerini temsil eder; imleç ise seçilen geçerli değeri gösterir. Dikey bir kaydırıcıda ise minimum değer üst uçta, maksimum değer ise alt uçta gösterilir. Bu değerler Minimum ve Maximum özellikleriyle temsil edilir ve varsayılan olarak 0 ile 100 arasındadır.
  • Kaydırıcının uçlarına tıklamak, tıklanan uca göre değeri bir artış (pozitif veya negatif) kadar değiştirir; bu artış, varsayılan değeri 1 olan SmallChange olarak adlandırılır.
  • Kaydırıcının her iki yanına tıklamak, tıklandığı uca göre değeri bir artış (pozitif veya negatif) kadar değiştirir; bu değer LargeChange olarak adlandırılır ve varsayılan değeri 10'dur.
  • Dikey bir kaydırıcının üst ucuna tıklandığında, değeri azalır. Bu durum, normalde değerin "artmasını" bekleyen ortalama bir kullanıcıyı şaşırtabilir. Bu sorun, SmallChange ve LargeChange özelliklerine negatif bir değer atanarak çözülür.
  • Bu beş özellik (Value, Minimum, Maximum, SmallChange, LargeChange) okuma ve yazma işlemlerine açıktır.
  • Sürücünün ana olayı, değer değişikliğini bildiren Scroll olayıdır.

NumericUpDown bileşeni sürücüye yakındır: bu bileşen de Minimum, Maximum ve Value özelliklerine sahiptir; varsayılan değerleri sırasıyla 0, 100, 0'dır. Ancak burada, Value özelliği, kontrolün ayrılmaz bir parçası olan bir giriş kutusunda görüntülenir. Kontrolün ReadOnly özelliği "true" olarak ayarlanmadıkça, kullanıcı bu değeri kendisi değiştirebilir. Artış değeri, Increment özelliği ile belirlenir; varsayılan değeri 1'dir. NumericUpDown bileşeninin ana olayı, değer değişikliğini bildiren olaydır: ValueChanged olayı

Uygulama kodu şu şekildedir:


using System.Windows.Forms;

namespace Chap5 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
            // regülatör 1'in özelliklerini belirliyoruz
            hScrollBar1.Value = 7;
            hScrollBar1.Minimum = 1;
            hScrollBar1.Maximum = 130;
            hScrollBar1.LargeChange = 11;
            hScrollBar1.SmallChange = 1;
            // 2 numaralı sürücüye 1 numaralı sürücüyle aynı özellikler verilir
            hScrollBar2.Value = hScrollBar1.Value;
            hScrollBar2.Minimum = hScrollBar1.Minimum;
            hScrollBar2.Maximum = hScrollBar1.Maximum;
            hScrollBar2.LargeChange = hScrollBar1.LargeChange;
            hScrollBar2.SmallChange = hScrollBar1.SmallChange;
            // artırıcı için de aynısı geçerlidir
            numericUpDown2.Value = hScrollBar1.Value;
            numericUpDown2.Minimum = hScrollBar1.Minimum;
            numericUpDown2.Maximum = hScrollBar1.Maximum;
            numericUpDown2.Increment = hScrollBar1.SmallChange;

            // Etikete 1 numaralı sürücünün değeri atanır
            labelValeurHS1.Text = hScrollBar1.Value.ToString();
        }

        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e) {
            // 1 numaralı sürücünün değeri değiştirilir
            // değeri, 2 numaralı sürücüye ve etikete yansıtılır
            hScrollBar2.Value = hScrollBar1.Value;
            labelValeurHS1.Text = hScrollBar1.Value.ToString();
        }

        private void numericUpDown2_ValueChanged(object sender, System.EventArgs e) {
            // artırıcı değeri değişti
            // 2. sürücünün değeri sabitlenir
            hScrollBar2.Value = (int)numericUpDown2.Value;
        }
    }
}

7.3. Fare olayları

Bir kap içinde çizim yaparken, örneğin tıklama sırasında bir nokta görüntülemek için farenin konumunu bilmek önemlidir. Farenin hareketleri, farenin içinde hareket ettiği kapta olaylara neden olur.

  • [1]: Form veya bir denetim üzerinde fare hareketi sırasında meydana gelen olaylar
  • [2]: Sürükle ve bırak (Drag'nDrop) işlemi sırasında meydana gelen olaylar
MouseEnter
fare, denetimin alanına yeni girdi
MouseLeave
fare kontrol alanından çıktı
MouseMove
fare kontrol alanı içinde hareket ediyor
MouseDown
Farenin sol tuşuna basıldı
MouseUp
Farenin sol tuşunun bırakılması
DragDrop
Kullanıcı bir nesneyi denetim üzerine bırakır
DragEnter
Kullanıcı bir nesneyi sürükleyerek kontrol alanına girer
DragLeave
kullanıcı bir nesneyi sürükleyerek kontrol alanından çıkar
DragOver
kullanıcı bir nesneyi sürükleyerek kontrol alanının üzerinden geçer

Aşağıda, farklı fare olaylarının ne zaman gerçekleştiğini daha iyi anlamanıza yardımcı olacak bir uygulama bulunmaktadır:

No
tür
ad
rol
1
Etiket
lblPositionSouris
Form 1, Liste 2 veya Düğme 3'te farenin konumunu görüntülemek için
2
ListBox
listBoxEvts
MouseMove dışındaki fare olaylarını görüntülemek için
3
Düğme
buttonEffacer
2'nin içeriğini silmek için

Üç kontrol üzerindeki fare hareketlerini takip etmek için tek bir işleyici yazılır: affiche işleyicisi:

affiche yordamının kodu şöyledir:


        private void affiche(object sender, MouseEventArgs e) {
            // fare hareketi - farenin (X,Y) koordinatları görüntülenir
            labelPositionSouris.Text = "(" + e.X + "," + e.Y + ")";
}

Fare bir kontrolün alanına her girdiğinde koordinat sistemi değişir. Fare için (0,0) başlangıç noktası, üzerinde bulunduğu kontrolün sol üst köşesidir. Böylece, çalıştırma sırasında fareyi formdan düğmeye getirdiğimizde koordinatlardaki değişikliği açıkça görebiliriz. Farenin alanındaki bu değişiklikleri daha iyi görebilmek için, denetimlerin Cursor [1] özelliğini kullanabiliriz:

Bu özellik, fare kontrol alanına girdiğinde fare imlecinin şeklini belirlemeye olanak tanır. Böylece örneğimizde, formun kendisi için imleci Default olarak ([2]), Liste 2 için Hand olarak ([3]) ve Düğme 3 için Cross olarak ([4]) ayarladık.

Ayrıca, Liste 2’ye farenin giriş ve çıkışlarını algılamak için, bu listenin MouseEnter ve MouseLeave olaylarını işliyoruz:


        private void listBoxEvts_MouseEnter(object sender, System.EventArgs e) {
            // olay bildirilir
            listBoxEvts.Items.Insert(0, string.Format("MouseEnter à {0:hh:mm:ss}",DateTime.Now));
        }

        private void listBoxEvts_MouseLeave(object sender, EventArgs e) {
            // olay bildiriliyor
            listBoxEvts.Items.Insert(0, string.Format("MouseLeave à {0:hh:mm:ss}", DateTime.Now));
}

Formdaki tıklamaları işlemek için MouseDown ve MouseUp olaylarını işliyoruz:


        private void listBoxEvts_MouseDown(object sender, MouseEventArgs e) {
            // olayı bildirilir
            listBoxEvts.Items.Insert(0, string.Format("MouseDown à {0:hh:mm:ss}", DateTime.Now));
        }

        private void listBoxEvts_MouseUp(object sender, MouseEventArgs e) {
            // olayı bildirir
            listBoxEvts.Items.Insert(0, string.Format("MouseUp à {0:hh:mm:ss}", DateTime.Now));
}
  • 3. ve 8. satırlar: En son olayların listede ilk sırada yer alması için mesajlar ListBox'te 1. sıraya yerleştirilir.
 

Son olarak, Effacer düğmesine tıklama işleyicisinin kodu:


        private void buttonEffacer_Click(object sender, EventArgs e) {
            listBoxEvts.Items.Clear();
}

7.4. Menülü bir pencere oluşturma

Şimdi menülü bir pencereyi nasıl oluşturacağımıza bakalım. Aşağıdaki pencereyi oluşturacağız:

Menü oluşturmak için "Menüler ve Araç Çubukları" çubuğundan "MenuStrip" bileşenini seçin:

  • [1]: [MenuStrip] bileşeninin seçilmesi
  • [2]: Böylece, "Type Here" başlıklı boş kutucuklar içeren bir menü form üzerine eklenir. Menüdeki farklı seçenekleri bu kutucuklara yazmanız yeterlidir.
  • [3]: "Seçenek A" etiketi girildi. [4] etiketine geçiyoruz.
  • [5]: A seçeneklerinin etiketleri girildi. [6] etiketine geçiyoruz.
  • [6]: İlk B seçenekleri
  • [7]: B1'in altına bir ayırıcı eklenir. Bu ayırıcı, "Type Here" metniyle ilişkili bir açılır menüde bulunur
  • [8]: Bir alt menü oluşturmak için [8] okunu kullanın ve [9]'e alt menüyü yazın

Şimdi formun çeşitli bileşenlerine isim vermek kalıyor:

no
tür
ad(lar)
rol
1
Etiket
labelStatut
tıklanan menü seçeneğinin metnini görüntülemek için
2
toolStripMenuItem
toolStripMenuItemOptionsA
toolStripMenuItemA1
toolStripMenuItemA2
toolStripMenuItemA3
"Seçenekler A" ana seçeneği altındaki menü seçenekleri
3
toolStripMenuItem
toolStripMenuItemOptionsB
toolStripMenuItemB1
toolStripMenuItemB2
toolStripMenuItemB3
"Seçenekler B" ana seçeneği altındaki menü seçenekleri
4
toolStripMenuItem
toolStripMenuItemB31
toolStripMenuItemB32
"B3" ana seçeneği altındaki menü seçenekleri

Menü seçenekleri, diğer görsel bileşenler gibi denetimlerdir ve özellikleri ile olayları vardır. Örneğin, A1 menü seçeneğinin özellikleri şunlardır:

 

Örneğimizde iki özellik kullanılmaktadır:

Name
menü kontrolünün adı
Text
menü seçeneğinin adı

Menü yapısında, A1 seçeneğini seçelim ve sağ tıklayarak kontrolün özelliklerine erişelim:

événements [1] sekmesinde, affiche [2] yöntemini Click olayına atayalım. Bu, A1 seçeneğine yapılan tıklamanın affiche adlı bir yöntem tarafından işlenmesini istediğimiz anlamına gelir. Visual Studio, kod penceresinde affiche yöntemini otomatik olarak oluşturur:


private void affiche(object sender, EventArgs e) {
        }

Bu yöntemde, tıklanan menü seçeneğinin Text özelliğini labelStatut etiketinde görüntülemekle yetineceğiz:


private void affiche(object sender, EventArgs e) {
            // TextBox'te seçilen alt menünün adını görüntüler
            labelStatut.Text = ((ToolStripMenuItem)sender).Text;
}

sender olayının kaynağı object türündedir. Menü seçenekleri ToolStripMenuItem türündedir, bu nedenle object'ten ToolStripMenuItem'e tür dönüştürme yapmak zorundayız.

Tüm menü seçenekleri için tıklama işleyicisini affiche [3,4] yöntemine ayarlıyoruz.

Uygulamayı çalıştırıp bir menü öğesini seçelim:

 

7.5. Görsel olmayan bileşenler

Şimdi bir dizi görsel olmayan bileşene odaklanacağız: bunlar tasarım aşamasında kullanılır, ancak uygulama sırasında görünmezler.

7.5.1. , OpenFileDialog ve SaveFileDialog diyalog pencereleri

Şu uygulamayı oluşturacağız:

Kontroller şunlardır:

No
tür
ad
rol
1
TextBox
TextBoxLignes
kullanıcı tarafından girilen veya bir dosyadan yüklenen metin
MultiLine=True, ScrollBars=Both, AccepReturn=True, AcceptTab=True
2
Düğme
buttonSauvegarder
[1]'teki metni bir metin dosyasına kaydetmeye olanak tanır
3
Düğme
buttonCharger
bir metin dosyasının içeriğini [1] dosyasına yüklemenizi sağlar
4
Düğme
buttonEffacer
[1] dosyasının içeriğini siler
5
SaveFileDialog
saveFileDialog1
[1] yedekleme dosyasının adını ve konumunu seçmeye yarayan bileşen. Bu bileşen, [7] araç çubuğundan alınır ve formun üzerine bırakılır. Böylece kaydedilir, ancak formda yer kaplamaz. Bu, görsel olmayan bir bileşendir.
6
OpenFileDialog
openFileDialog1
[1]'e yüklenecek dosyayı seçmeye yarayan bileşen.

Effacer düğmesine ait kod basittir:


        private void buttonEffacer_Click(object sender, EventArgs e) {
            // TexBox'e boş dize eklenir
            textBoxLignes.Text = "";
}

SaveFileDialog sınıfının aşağıdaki özelliklerini ve yöntemlerini kullanacağız:

Alan
Tür
Rol
string Filter
Propriété
diyalog penceresindeki dosya türü açılır menüsünde sunulan dosya türleri
int FilterIndex
Propriété
Yukarıdaki listede varsayılan olarak önerilen dosya türü numarası. 0'dan başlar.
string InitialDirectory
Propriété
dosyanın kaydedilmesi için başlangıçta gösterilen klasör
string FileName
Propriété
kullanıcı tarafından belirtilen yedekleme dosyasının adı
DialogResult.ShowDialog()
Méthode
Yedekleme iletişim kutusunu görüntüleyen yöntem. DialogResult türünde bir sonuç döndürür.

ShowDialog yöntemi, aşağıdakine benzer bir iletişim kutusu görüntüler:

1
Filter özelliğinden oluşturulan açılır liste. Varsayılan olarak önerilen dosya türü, FilterIndex ile belirlenir
2
geçerli klasör, bu özellik girilmişse InitialDirectory ile belirlenir
3
kullanıcı tarafından seçilen veya doğrudan girilen dosya adı. FileName özelliğinde kullanılabilir olacaktır
4
Kaydet/İptal düğmeleri. Enregistrer düğmesi kullanılırsa, ShowDialog işlevi DialogResult.OK sonucunu verir

Kaydetme prosedürü şu şekilde yazılabilir:


private void buttonSauvegarder_Click(object sender, System.EventArgs e) {
            // giriş kutusu bir metin dosyasına kaydedilir
            // savefileDialog1 iletişim kutusunu yapılandırır
            saveFileDialog1.InitialDirectory = Application.ExecutablePath;
            saveFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*";
            saveFileDialog1.FilterIndex = 0;
            // diyalog kutusu görüntülenir ve sonucu alınır
            if (saveFileDialog1.ShowDialog() == DialogResult.OK) {
                // dosya adı alınır
                string nomFichier = saveFileDialog1.FileName;
                StreamWriter fichier = null;
                try {
                    // dosyayı yazma modunda açıyoruz
                    fichier = new StreamWriter(nomFichier);
                    // içine metin yazılır
                    fichier.Write(textBoxLignes.Text);
                } catch (Exception ex) {
                    // sorun
                    MessageBox.Show("Problème à l'écriture du fichier (" +
                    ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                } finally {
                    // dosyayı kapatıyoruz
                    if (fichier != null) {
                        fichier.Dispose();
                    }
                }
            }
        }
  • 4. satır: başlangıç klasörü (InitialDirectory), uygulamanın yürütülebilir dosyasını içeren klasöre (Application.ExecutablePath) ayarlanır.
  • 5. satır: Görüntülenecek dosya türleri belirlenir. Filtrelerin sözdizimi şöyledir: filtre1|filtre2|..|filtren avec filtrei= Texte| dosya şablonu. Burada kullanıcı, *.txt ve *.* dosyaları arasında seçim yapabilir.
  • 6. satır: Kullanıcıya ilk olarak gösterilecek dosya türü belirlenir. Burada 0 indeksi, *.txt dosyalarını belirtir.
  • 8. satır: İletişim kutusu görüntülenir ve sonucu alınır. Diyalog penceresi görüntülenirken, kullanıcı ana forma erişemez (modal diyalog penceresi). Kullanıcı kaydedilecek dosyanın adını belirler ve diyalog penceresinden ya Enregistrer düğmesiyle, ya Annuler, düğmesiyle ya da pencereyi kapatarak çıkar. ShowDialog yönteminin sonucu, yalnızca kullanıcı iletişim kutusundan çıkmak için Enregistrer düğmesini kullanmışsa DialogResult.OK olur.
  • Bu işlem tamamlandığında, oluşturulacak dosyanın adı artık saveFileDialog1 nesnesinin FileName özelliğinde yer alır. Böylece, klasik bir metin dosyası oluşturma işlemine geri dönülür. TextBox: textBoxLignes.Text içeriği yazılırken, meydana gelebilecek istisnalar yönetilir.

OpenFileDialog sınıfı, SaveFileDialog sınıfına çok benzemektedir. Daha önce kullandığımız yöntem ve özelliklerin aynısı kullanılacaktır. ShowDialog yöntemi, aşağıdakine benzer bir iletişim kutusu görüntüler:

1
Filter özelliğinden oluşturulan açılır liste. Varsayılan olarak önerilen dosya türü, FilterIndex ile belirlenir
2
geçerli klasör, bu özellik doldurulmuşsa InitialDirectory ile belirlenir
3
kullanıcı tarafından seçilen veya doğrudan girilen dosya adı. FileName özelliğinde kullanılabilir olacaktır
4
Aç/İptal düğmeleri. Ouvrir düğmesi kullanılırsa, ShowDialog işlevi DialogResult.OK sonucunu verir

Metin dosyasını yükleme prosedürü şu şekilde yazılabilir:


private void buttonCharger_Click(object sender, EventArgs e) {
            // metin dosyasını giriş kutusuna yüklüyoruz
            // openfileDialog1 iletişim kutusunu ayarlıyoruz
            openFileDialog1.InitialDirectory = Application.ExecutablePath;
            openFileDialog1.Filter = "Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*";
            openFileDialog1.FilterIndex = 0;
            // diyalog penceresi görüntülenir ve sonucu alınır
            if (openFileDialog1.ShowDialog() == DialogResult.OK) {
                // dosya adı alınır
                string nomFichier = openFileDialog1.FileName;
                StreamReader fichier = null;
                try {
                    // dosyayı okuma modunda açıyoruz
                    fichier = new StreamReader(nomFichier);
                    // dosyanın tamamı okunur ve TextBox'e aktarılır
                    textBoxLignes.Text = fichier.ReadToEnd();
                } catch (Exception ex) {
                    // sorun
                    MessageBox.Show("Problème à la lecture du fichier (" +
                    ex.Message + ")", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                } finally {
                    // dosyayı kapatıyoruz
                    if (fichier != null) {
                        fichier.Dispose();
                    }
                }//Son olarak
            }//eğer
        }
  • 4. satır: başlangıç klasörü (InitialDirectory), uygulamanın yürütülebilir dosyasını içeren klasöre (Application.ExecutablePath) ayarlanır.
  • 5. satır: Görüntülenecek dosya türleri belirlenir. Filtrelerin sözdizimi şöyledir: filtre1|filtre2|..|filtren avec filtrei= Texte| dosya şablonu. Burada kullanıcı, *.txt ve *.* dosyaları arasında seçim yapabilir.
  • 6. satır: Kullanıcıya ilk olarak gösterilecek dosya türü belirlenir. Burada 0 indeksi, *.txt dosyalarını belirtir.
  • 8. satır: İletişim kutusu görüntülenir ve sonucu alınır. Diyalog penceresi görüntülenirken, kullanıcı ana forma erişemez (modal diyalog penceresi). Kullanıcı kaydedilecek dosyanın adını belirler ve diyalog penceresinden ya Ouvrir düğmesiyle, ya da Annuler, düğmesiyle ya da pencereyi kapatarak çıkar. ShowDialog yönteminin sonucu, yalnızca kullanıcı iletişim kutusundan çıkmak için Enregistrer düğmesini kullanmışsa DialogResult.OK olur.
  • Bu işlem tamamlandıktan sonra, oluşturulacak dosyanın adı artık FileName nesnesinin openFileDialog1 özelliğinde yer almaktadır. Ardından, klasik bir metin dosyası okuma işlemine geri dönülür. 16. satırda, bir dosyanın tamamını okumaya olanak tanıyan yönteme dikkat edilmelidir.

7.5.2. FontColor ve ColorDialog iletişim kutuları

Önceki örneği, iki yeni düğme ve iki yeni görsel olmayan denetim ekleyerek devam ettiriyoruz:

6

7

No
tür
ad
rol
1
Düğme
buttonCouleur
TextBox karakterlerinin rengini ayarlamak için
2
Düğme
buttonPolice
TextBox'in yazı tipini ayarlamak için
3
ColorDialog
colorDialog1
renk seçimi sağlayan bileşen - [5] araç setinden alınmıştır.
4
FontDialog
colorDialog1
yazı tipi seçimi sağlayan bileşen - [5] araç setinden alınmıştır.

FontDialog ve ColorDialog sınıfları, OpenFileDialog ve SaveFileDialog sınıflarındaki ShowDialog yöntemine benzer bir ShowDialog yöntemine sahiptir.

ColorDialog sınıfındaki ShowDialog yöntemi, bir [1] rengi seçmeye olanak tanır. FontDialog sınıfındaki yöntem ise bir yazı tipi seçmeye olanak tanır:

  • [1]: Kullanıcı OK düğmesiyle iletişim kutusundan çıkarsa, ShowDialog yönteminin sonucu DialogResult.OK olur ve seçilen renk, kullanılan ColorDialog nesnesinin Color özelliğinde bulunur.
  • [2]: Kullanıcı, OK düğmesiyle iletişim kutusundan çıkarsa, ShowDialog yönteminin sonucu DialogResult.OK olur ve seçilen yazı tipi, kullanılan FontDialog nesnesinin Font özelliğinde bulunur.

Artık Couleur ve Police düğmelerine yapılan tıklamaları işlemek için gerekli öğelere sahibiz:


        private void buttonCouleur_Click(object sender, EventArgs e) {// metin rengi seçimi
            if (colorDialog1.ShowDialog() == DialogResult.OK) {
                // TextBox'in Forecolor özelliğini değiştiriyoruz
                textBoxLignes.ForeColor = colorDialog1.Color;
            }//if
        }

        private void buttonPolice_Click(object sender, EventArgs e) {
            // yazı tipi seçimi
            if (fontDialog1.ShowDialog() == DialogResult.OK) {
                // TextBox'in Font özelliğini değiştirme
                textBoxLignes.Font = fontDialog1.Font;
}
  • [4] satırı: TextBox bileşeninin [ForeColor] özelliği, TextBox'teki karakterlerin [Color] türündeki rengini belirtir. Burada bu renk, [ColorDialog] türündeki iletişim kutusunda kullanıcı tarafından seçilen renktir.
  • [12] satırı: TextBox bileşeninin [Font] özelliği, TextBox karakterlerinin [Font] türündeki yazı tipini belirtir. Burada bu yazı tipi, [FontDialog] türündeki iletişim kutusunda kullanıcı tarafından seçilen yazı tipidir.

7.5.3. Zamanlayıcı

Burada şu uygulamayı yazmayı öneriyoruz:

No
Tür
Ad
Rol
1
Etiket
labelChrono
bir kronometre gösterir
2
Düğme
buttonArretMarche
zamanlayıcının Durdur/Başlat düğmesi
3
Zamanlayıcı
timer1
burada her saniye bir olay gönderen bileşen

[4]'te kronometrenin çalıştığını, [5]'te ise kronometrenin durduğunu görüyoruz.

LabelChrono etiketinin içeriğini her saniye değiştirmek için, her saniye bir olay üreten bir bileşene ihtiyacımız var; bu olayı yakalayarak kronometrenin ekranını güncelleyebiliriz. Bu bileşen, Components [2] araç setinde bulunan Timer [1]'tir:

Burada kullanılan Timer bileşeninin özellikleri şu şekilde olacaktır:

Interval
bir Tick olayının tetikleneceği milisaniye sayısı.
Tick
Interval milisaniyenin sonunda üretilen olay
Enabled
zamanlayıcıyı etkin (true) veya devre dışı (false) hale getirir

Örneğimizde zamanlayıcının adı timer1'tir ve timer1.Interval değeri 1000 ms (1 saniye) olarak ayarlanmıştır. Dolayısıyla Tick olayı her saniye gerçekleşecektir. Durdur/Çalıştır düğmesine tıklama, aşağıdaki buttonArretMarche_Click yordamı tarafından işlenir:


using System;
using System.Windows.Forms;

namespace Chap5 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        // örnek değişkeni
        private DateTime début = DateTime.Now;
...
        private void buttonArretMarche_Click(object sender, EventArgs e) {
            // kapalı mı, açık mı?
            if (buttonArretMarche.Text == "Marche") {
                // başlangıç saatini not ediyoruz
                début = DateTime.Now;
                // ekranı görüntülenir
                labelChrono.Text = "00:00:00";
                // zamanlayıcıyı başlat
                timer1.Enabled = true;
                // düğmenin etiketini değiştir
                buttonArretMarche.Text = "Arrêt";
                // bitiş
                return;
            }//
            if (buttonArretMarche.Text == "Arrêt") {
                // zamanlayıcı durdurulur
                timer1.Enabled = false;
                // düğmenin etiketini değiştir
                buttonArretMarche.Text = "Marche";
                // son
                return;
            }
        }

    }
}
  • 13. satır: Durdur/Çalıştır düğmesine tıklamayı işleyen prosedür.
  • 15. satır: Durdur/Çalıştır düğmesinin etiketi ya "Durdur" ya da "Çalıştır"dır. Dolayısıyla ne yapılacağını belirlemek için bu etiketi kontrol etmek gerekir.
  • 17. satır: "Çalıştır" seçeneği durumunda, başlangıç saati, form nesnesinin (11. satır) bir küresel değişkeni olan début değişkenine kaydedilir
  • 19. satır: LabelChrono etiketinin içeriği başlatılır
  • 21. satır: Zamanlayıcı başlatılır (Enabled=true)
  • 23. satır: Düğmenin etiketi "Dur" olarak değişir.
  • 27. satır: "Durdur" seçeneği seçildiğinde
  • 29. satır: zamanlayıcı durdurulur (Enabled=false)
  • satır 31: düğmenin etiketi "Çalıştır" olarak değiştirilir.

Geriye, Tick nesnesindeki timer1 olayını işlemek kalıyor; bu olay her saniye gerçekleşir:


private void timer1_Tick(object sender, EventArgs e) {
            // bir saniye geçti
            DateTime maintenant = DateTime.Now;
            TimeSpan durée = maintenant - début;
            // zamanlayıcı güncelleniyor
            labelChrono.Text = durée.Hours.ToString("d2") + ":" + durée.Minutes.ToString("d2") + ":" + durée.Seconds.ToString("d2");
        }
  • 3. satır: O anki saati kaydediyoruz
  • 4. satır: Kronometrenin başlatılma saatinden itibaren geçen süre hesaplanır. Sonuç olarak, zaman aralığını temsil eden TimeSpan türünde bir nesne elde edilir.
  • 6. satır: Bu değer, kronometrede hh:mm:ss biçiminde görüntülenmelidir. Bunun için, Hours, Minutes, Seconds özelliklerini kullanıyoruz; bunlar sırasıyla saat, dakika ve saniyeyi temsil eder ve 2 basamaklı bir görüntü elde etmek için ToString("d2") biçiminde görüntülenir.

7.6. Örnek uygulama - sürüm 6

IMPOTS örnek uygulamasını ele alalım. En son sürümü 6.4. paragrafta incelenmişti. Bu, aşağıdaki üç katmanlı uygulamaydı:

  • [metier] ve [dao] katmanları, DLL içinde kapsüllenmişti
  • [ui] katmanı, bir [console] katmanıydı
  • Katmanların oluşturulması ve uygulamaya entegrasyonu Spring tarafından sağlanıyordu.

Bu yeni sürümde, [ui] katmanı aşağıdaki grafik arayüz tarafından sağlanacaktır:

 

7.6.1. Visual Studio çözümü

Visual Studio çözümü aşağıdaki öğelerden oluşur:

  • [1]: Proje aşağıdaki unsurlardan oluşur:
  • [Program.cs]: Uygulamayı başlatan sınıf
  • [Form1.cs]: ilk formun sınıfı
  • [Form2]: İkinci formun sınıfı
  • [lib], [2] içinde ayrıntılı olarak yer almaktadır: buraya proje için gerekli tüm DLL'ler eklenmiştir:
  • [ImpotsV5-dao.dll]: 6.4.3. paragrafta oluşturulan [dao] katmanına ait DLL;
  • [ImpotsV5-metier.dll]: 6.4.4. paragrafta oluşturulan [dao] katmanına ait DLL;
  • [Spring.Core.dll], [Common.Logging.dll], [antlr.runtime.dll]: önceki sürümde zaten kullanılmış olan Spring'e ait DLL'ler (bkz. paragraf 6.4.6).
  • [3] dosyasında ayrıntıları verilen [references]: proje referansları. [lib] klasöründeki her bir DLL dosyası için bir referans eklenmiştir
  • [App.config]: projenin yapılandırma dosyası. Bu dosya, 6.4.6. paragrafında açıklanan önceki sürümdeki dosya ile aynıdır;
  • [DataImpot.txt]: [4] proje yürütme klasörüne otomatik olarak kopyalanacak şekilde yapılandırılmış vergi dilimleri dosyası

[Form1] formu, daha önce sunulan [A] vergi hesaplama parametrelerinin girildiği formdur. [Form2] ve [B] formları, bir hata mesajını görüntülemek için kullanılır:

7.6.2. [Program.cs] sınıfı

[Program.cs] sınıfı uygulamayı başlatır. Kodu şöyledir:


using System;
using System.Windows.Forms;
using Spring.Context;
using Spring.Context.Support;
using Metier;
using System.Text;

namespace Chap5 {
    static class Program {
        /// <summary>
        /// Uygulamanın ana giriş noktası.
        /// </summary>
        [STAThread]
        static void Main() {
            // Vs tarafından oluşturulan kod
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // --------------- Geliştirici kodu
            // [metier] ve [dao] katmanlarının örneklendirmeleri
            IApplicationContext ctx = null;
            Exception ex = null;
            IImpotMetier metier = null;
            try {
                // Spring bağlamı
                ctx = ContextRegistry.GetContext();
                // [metier] katmanında bir referans isteniyor
                metier = (IImpotMetier)ctx.GetObject("metier");
            } catch (Exception e1) {
                // istisna kaydı
                ex = e1;
            }
            // görüntülenecek form
            Form form = null;
            // Bir istisna oluştu mu?
            if (ex != null) {
                // evet - görüntülenecek hata mesajı oluşturulur
                StringBuilder msgErreur = new StringBuilder(String.Format("Chaîne des exceptions : {0}{1}", "".PadLeft(40, '-'), Environment.NewLine));
                Exception e = ex;
                while (e != null) {
                    msgErreur.Append(String.Format("{0}: {1}{2}", e.GetType().FullName, e.Message, Environment.NewLine));
                    msgErreur.Append(String.Format("{0}{1}", "".PadLeft(40, '-'), Environment.NewLine));
                    e = e.InnerException;
                }
                // görüntülenecek hata mesajının aktarıldığı hata penceresi oluşturuluyor
                Form2 form2 = new Form2();
                form2.MsgErreur = msgErreur.ToString();
                // bu, görüntülenecek pencere olacaktır
                form = form2;
            } else {
                // her şey yolunda gitti
                // [Form1] grafik arayüzü oluşturuldu; bu arayüze [metier] katmanındaki referans aktarılıyor
                Form1 form1 = new Form1();
                form1.Metier = metier;
                // bu, görüntülenecek pencere olacak
                form = form1;
            }
            // pencerenin görüntülenmesi
            Application.Run(form);
        }
    }
}

Visual Studio tarafından oluşturulan kod, 19. satırdan itibaren tamamlanmıştır. Uygulama, aşağıdaki [App.config] dosyasını kullanır :


<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <configSections>
        <sectionGroup name="spring">
            <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
            <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
        </sectionGroup>
    </configSections>

    <spring>
        <context>
            <resource uri="config://spring/objects" />
        </context>
        <objects xmlns="http://www.springframework.net">
            <object name="dao" type="Dao.FileImpot, ImpotsV5-dao">
                <constructor-arg index="0" value="DataImpot.txt"/>
            </object>
            <object name="metier" type="Metier.ImpotMetier, ImpotsV5-metier">
                <constructor-arg index="0" ref="dao"/>
            </object>
        </objects>
    </spring>
</configuration>
  • 24-32. satırlar: [App.config] dosyasını kullanarak [metier] ve [dao] katmanlarının örnekleri oluşturulur
  • 26. satır: [App.config] dosyasının kullanılması
  • 28. satır: [metier] katmanından bir referans alınması
  • satır 31: Olası istisnanın kaydedilmesi
  • satır 34: form referansı, görüntülenecek formu (form1 veya form2) belirleyecektir
  • satır 36-50: istisna meydana gelmişse, [Form2] türünde bir formun görüntülenmesine hazırlanılır
  • satır 38-44: Görüntülenecek hata mesajı oluşturulur. Bu mesaj, istisna zincirinde bulunan çeşitli istisnaların hata mesajlarının birleştirilmesiyle oluşturulur.
  • 46. satır: [Form2] türünde bir form oluşturulur.
  • 47. satır: Daha sonra göreceğimiz üzere, bu formun MsgErreur adlı bir genel özelliği vardır; bu, görüntülenecek hata mesajıdır:

        public string MsgErreur { private get; set; }

Bu özellik doldurulur.

  • 49. satır: Görüntülenecek pencereyi belirten form referansı başlatılır. Burada polimorfizmin iş başında olduğunu not edelim. form2, [Form] türünde değil, [Form2] türündedir; bu da [Form]'ten türetilmiş bir türdür.
  • 50-57. satırlar: Herhangi bir istisna oluşmamıştır. [Form1] türünde bir formun görüntülenmesine hazırlanılmaktadır.
  • 53. satır: [Form1] türünde bir form oluşturulur.
  • 54. satır: Daha sonra göreceğimiz üzere, bu formun Metier adlı bir genel özelliği vardır; bu özellik, [metier] katmanına bir referanstır:

                public IImpotMetier Metier { private get; set; }

Bu özelliği dolduruyoruz.

  • 56. satır: Görüntülenecek pencereyi belirten form referansı başlatılır. Burada da polimorfizmin iş başında olduğunu tekrar not edelim. form1, [Form] türünde değil, [Form]'ten türetilmiş bir tür olan [Form1] türündedir.
  • 59. satır: form tarafından referans verilen pencere görüntülenir.

7.6.3. [Form1] formu

[conception] modunda [Form1] formu şu şekildedir:

Kontroller şunlardır

No
tür
ad
rol
0
GroupBox
groupBox1
Text=Evli misiniz?
1
RadioButton
radioButtonOui
evliyseniz işaretleyin
2
RadioButton
radioButtonNon
evli değilse işaretlenir
Checked=True
3
NumericUpDown
numericUpDownEnfants
Vergi mükellefinin çocuk sayısı
Minimum=0, Maksimum=20, Artım=1
4
TextBox
textSalaire
Vergi mükellefinin yıllık maaşı (avro cinsinden)
5
Etiket
labelImpot
ödenecek vergi tutarı
BorderStyle=Fixed3D
6
Düğme
buttonCalculer
vergi hesaplamasını başlat
7
Düğme
buttonEffacer
formu yüklendiği zamanki haline geri döndürür
8
Düğme
buttonQuitter
uygulamadan çıkmak için

Formun çalışma kuralları

  • Maaş alanında herhangi bir giriş yapılmadığı sürece Calculer düğmesi kapalı kalır
  • hesaplama başlatıldığında maaşın yanlış olduğu tespit edilirse, hata bildirilir [9]

Sınıf kodu şöyledir:


using System.Windows.Forms;
using Metier;
using System;

namespace Chap5 {
    public partial class Form1 : Form {
        // [métier] katmanı
        public IImpotMetier Metier { private get; set; }

        public Form1() {
            InitializeComponent();
        }

        private void buttonCalculer_Click(object sender, System.EventArgs e) {
            // maaş doğru mu
            int salaire;
            bool ok=int.TryParse(textSalaire.Text.Trim(), out salaire);
            if (! ok  || salaire < 0) {
                // hata mesajı
                MessageBox.Show("Salaire incorrect", "Erreur de saisie", MessageBoxButtons.OK, MessageBoxIcon.Error);
                // hatalı alana geri dön
                textSalaire.Focus();
                // giriş alanındaki metnin seçilmesi
                textSalaire.SelectAll();
                // giriş arayüzüne geri dönüş
                return;
            }
            // maaş doğru - vergi hesaplanabilir
            labelImpot.Text = Metier.CalculerImpot(radioButtonOui.Checked, (int)numericUpDownEnfants.Value, salaire).ToString();
        }

        private void buttonQuitter_Click(object sender, System.EventArgs e) {
            Environment.Exit(0);
        }

        private void buttonEffacer_Click(object sender, System.EventArgs e) {
            // formu sıfırla
            labelImpot.Text = "";
            numericUpDownEnfants.Value = 0;
            textSalaire.Text = "";
            radioButtonNon.Checked = true;
        }

        private void textSalaire_TextChanged(object sender, EventArgs e) {
            // [Calculer] düğmesinin durumu
            buttonCalculer.Enabled=textSalaire.Text.Trim()!="";
        }

    }
}

Sadece önemli kısımları açıklıyoruz:

  • [8] satırı: Metier kamu özelliği, başlatma sınıfı [Program.cs]'in [Form1]'e [metier] katmanına ilişkin bir referans eklemesine olanak tanır.
  • [14] satırı: vergi hesaplama prosedürü
  • 15-27. satırlar: maaşın geçerliliğinin kontrolü (0'dan büyük bir tamsayı).
  • 29. satır: [metier] katmanındaki [CalculerImpot] yöntemi kullanılarak verginin hesaplanması. [metier] katmanının bir DLL içine kapsüllenmesi sayesinde bu işlemin ne kadar basitleştiğine dikkat edilmelidir.

7.6.4. [Form2] formu

[conception] modunda [Form2] formu şu şekildedir:

Kontroller şunlardır

No
tür
ad
rol
1
TextBox
textBoxErreur
Multiline=True, Scrollbars=Both

Sınıfın kodu şöyledir:


using System.Windows.Forms;

namespace Chap5 {
    public partial class Form2 : Form {
        // hata mesajı
        public string MsgErreur { private get; set; }

        public Form2() {
            InitializeComponent();
        }

        private void Form2_Load(object sender, System.EventArgs e) {
            // hata mesajı görüntüleniyor
            textBoxErreur.Text = MsgErreur;
            // tüm metnin seçimi kaldırılıyor
            textBoxErreur.Select(0, 0);
        }
    }
}
  • 6. satır: MsgErreur kamu özelliği, [Program.cs] başlatma sınıfının, görüntülenecek hata mesajını [Form2]'e eklemesine olanak tanır. Bu mesaj, Load olayının işlenmesi sırasında (12-16. satırlar) görüntülenir.
  • 14. satır: Hata mesajı TextBox'e yerleştirilir
  • 16. satır: Bir önceki işlemde yapılan seçim kaldırılır. [TextBox].Select(başlangıç, uzunluk) komutu, longueur karakterini début numaralı karakterden itibaren seçer (vurgular). [TextBox].Select(0,0) komutu, tüm metnin seçimini kaldırır.

7.6.5. Sonuç

Kullanılan üç katmanlı mimariye tekrar göz atalım:

Bu mimari, [ui] katmanının mevcut konsol uygulamasını bir grafik uygulamasıyla değiştirmemize olanak sağladı; [metier] ve [dao] katmanlarında ise hiçbir değişiklik yapmadık. Diğer katmanlar üzerindeki olası etkiler konusunda endişelenmeden [ui] katmanına odaklanabildik. İşte 3 katmanlı mimarilerin en önemli avantajı budur. Bunun bir başka örneğini ileride göreceğiz; şu anda bir metin dosyasındaki verileri işleyen [dao] katmanı, bir veritabanındaki verileri işleyen [dao] katmanıyla değiştirildiğinde. Bunun, [ui] ve [metier] katmanları üzerinde hiçbir etki yaratmadan gerçekleşeceğini göreceğiz.