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:
pencerenin arka plan rengini ayarlamak için | |
penceredeki çizimlerin veya metnin rengini ayarlamak için | |
pencereye bir menü eklemek için | |
pencereye bir başlık vermek için | |
pencere türünü belirlemek için | |
penceredeki yazıların yazı tipini ayarlamak için | |
pencerenin adını ayarlamak için |
Burada, Text ve Name özelliklerini ayarlıyoruz:
Girişler ve düğmeler - 1 | |
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:
- birlikte biçimlendirilecek farklı bileşenleri seçin (bileşenleri seçerken Ctrl tuşunu basılı tutun)
- 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
görüntülenecek mesaj | |
pencerenin başlığı | |
pencerede bulunan düğmeler | |
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:
düğmeler | |
![]() | |
![]() | |
![]() | |
![]() | |
![]() | |
![]() |
icon parametresi, yukarıda (10. satırda gösterildiği gibi MessageBoxIcon ön ekiyle) belirtilen sabitler arasından değer alabilir:
![]() | aynı Stop | ||
aynı Uyarı | ![]() | ||
Aynı şekilde Asterisk | ![]() | ||
![]() | aynı şekilde El | ||
![]() |
Show yöntemi, bir sıralama olan [System.Windows.Forms.DialogResult] türünde bir sonuç döndüren statik bir yöntemdir:

Kullanıcının MessageBox türündeki pencereyi kapatmak için hangi düğmeye bastığını öğrenmek için şunu yazacağız:
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:
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 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:
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.
form yükleniyor | |
Form kapatılıyor | |
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:
birden fazla satır metin kabul etmek için | |
kontrolün kaydırma çubuklarına sahip olmasını (Yatay, Dikey, Her İkisi) veya sahip olmamasını (Yok) belirlemek için | |
true olarak ayarlandığında, Enter tuşu satır sonu işlevi görür | |
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:
açılır liste içermeyen, düzenleme alanı bulunan liste | |
düzenleme alanı içeren açılır liste | |
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:
boş bir açılır liste oluşturur |
ComboBox öğeleri, Items özelliğinde bulunur:
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:
Combo'daki öğe sayısı | |
kombinasyon menüsünün i numaralı öğesi | |
o nesnesini kombinasyonun son öğesi olarak ekler | |
kombinasyonun sonuna bir nesne tablosu ekler | |
o nesnesini kombo menüsünün i konumuna ekler | |
kombinasyon menüsünden i numaralı öğeyi kaldırır | |
o nesnesini kombo listesinden kaldır | |
kombinasyondaki tüm öğeleri sil | |
o nesnesini açılır menüdeki i konumuna getirir | |
seçilen öğenin dizini | |
seçilen öğe | |
seçilen öğenin görüntülenen metni | |
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:
yalnızca tek bir öğe seçilebilir | |
ç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. | |
ç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
fare, denetimin alanına yeni girdi | |
fare kontrol alanından çıktı | |
fare kontrol alanı içinde hareket ediyor | |
Farenin sol tuşuna basıldı | |
Farenin sol tuşunun bırakılması | |
Kullanıcı bir nesneyi denetim üzerine bırakır | |
Kullanıcı bir nesneyi sürükleyerek kontrol alanına girer | |
kullanıcı bir nesneyi sürükleyerek kontrol alanından çıkar | |
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:
menü kontrolünün adı | |
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 |
Propriété | diyalog penceresindeki dosya türü açılır menüsünde sunulan dosya türleri | |
Propriété | Yukarıdaki listede varsayılan olarak önerilen dosya türü numarası. 0'dan başlar. | |
Propriété | dosyanın kaydedilmesi için başlangıçta gösterilen klasör | |
Propriété | kullanıcı tarafından belirtilen yedekleme dosyasının adı | |
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:
![]() |
Filter özelliğinden oluşturulan açılır liste. Varsayılan olarak önerilen dosya türü, FilterIndex ile belirlenir | |
geçerli klasör, bu özellik girilmişse InitialDirectory ile belirlenir | |
kullanıcı tarafından seçilen veya doğrudan girilen dosya adı. FileName özelliğinde kullanılabilir olacaktır | |
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:
![]() |
Filter özelliğinden oluşturulan açılır liste. Varsayılan olarak önerilen dosya türü, FilterIndex ile belirlenir | |
geçerli klasör, bu özellik doldurulmuşsa InitialDirectory ile belirlenir | |
kullanıcı tarafından seçilen veya doğrudan girilen dosya adı. FileName özelliğinde kullanılabilir olacaktır | |
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:
bir Tick olayının tetikleneceği milisaniye sayısı. | |
Interval milisaniyenin sonunda üretilen olay | |
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.


































































