|
Application ile ApplicationContext Sınıfı ve Visual Basic Projeleri |
|
2008 yılının son aylarında yayınlanan C# 3.0 kitabımın içeriği ve konuların ele alınış şekli hakkında potansiyel okurların fikir sahibi olmasını sağlamak için kişisel sitemde yayınlanacak bölümü seçmek zor olmamıştı. Çünkü Programcılar İçin Yazarlık Dersleri adlı PDF’yi hazırlarken C# 3.0 kitabımdan aldığım “C# Uygulamalarında Word’den Yararlanmak” ve “Exception Sınıfları” adlı 2 bölümden yararlanmaya karar vermiştim. Dolayısıyla bu uzunca 2 bölümü kişisel sitemde yayınlamam gerekiyordu. Ancak konu Visual Basic 9.0 kitabımdan örnek bir bölümü seçip yayınlamak olduğunda seçim yapmak kolay olmadı.
Sonunda tercihimi Application Sınıfı aldı 32 sayfalık bölümden yana yaptım. Çünkü bu bölümde yazdıklarımın neredeyse tamamını başka kaynaklarda bulma imkanı son derece düşüktü. Elbette başka kaynaklarda Application sınıfının birkaç metodundan Application sınıfından bağımsız söz edilmiyor değil. Bu söz etmenin nedeni Application sınıfını anlatmaktan öte söz konusu işlemi yapmaktır. Örneğin Application sınıfının Idle metodu hakkında bilgiyi birkaç satır olarak birçok kaynakta bulabilirsiniz.
Tabi Application sınıfıyla ilgili olarak Visual Basic 9.0 kitabıma yazdıklarımı olduğu gibi buraya almadım; küçük eklemeler ve değişiklikler yapıp öyle yayınladım. Çünkü bu makaleyi buradan elinde Visual Basic 9.0 kitabım olmayanlar okuyacaktı ve bölümün orijinalinde kitaptaki başka bölümlere, sayfalara göndermeler vardı. Bu nedenle kitap için hazırlamış olduğum orijinal metinde küçük değişiklikler yaptım. Ayrıca kitabın aksine ekran görüntülerini küçültmeyip orijinal büyüklükleriyle kullandım. Yaptığım bu küçük ekleme ve çıkarmalardan dolayı ellerinde Visual Basic 9.0 kitabım olan bazı okurlar Application sınıfıyla ilgili bilgilerini tazelemek için bu değiştirdiğim metni okumayı tercih edeceklerini tahmin ediyorum.
Şimdiye kadar kitapta birkaç kez işaret edildiği gibi(bu bölüm kitabın tam ortasında, 523. sayfasında başlamaktadır) Visual Studio ile gelen Windows Forms Application şablonu kullanılarak Visual Basic projesi hazırlandığı zaman karşınıza “Form1” adında bir form gelmektedir. Bu şablon ile hazırlanan Visual Basic projesinde değişiklik yapılmadan çalıştırıldığında projedeki “Form1” sınıfının örneği alınıp projenin başlangıç formu olarak ekrana gelmektedir. Projenin başlangıç formu kapatıldığında ise projenin çalışması sona ermektedir. Bu paragrafta yazılanlar yabacısı olduğunuz konular değildir. Tabi hemen bazıları itiraz edip 'bize neden bildiğimiz konuları anlatıyorsunuz?' diyebilirler. Orada burada sırf programcılık konulu kitaplar yazdı diye Memik Yanık’a küfür eden çok sayıda kişi varken itiraz edenlere başımla beraber deyip cevap vermek isterim.
Şimdi gelin Visual Studio ile gelen Windows Forms Application şablonu ile hazırlanan projenin geri planında nelerin olduğuna biraz bakalım. Bu amaçla Visual Studio ile “Proje1” adında yeni proje hazırlayıp varsayılan dosya adlarına bağlı kalıp kaydettim. Kaydetme işlemi sonucu hazırlanan dosyaları ve klasörleri aşağıda görebilirsiniz. Visual Basic projesini Visual Studio yerine Visual Basic’e özel Express Edition’la hazırlayanlar için değişen bir şey yoktur. Visual Studio’nun hazırladığı dosya adlarına bağlı kalarak aynı zamanda dosya adı çalma suçlamasından yırtmış oluyorum.
Visual Studio ile Visual Basic projesi hazırlayıp herhangi bir değişiklik yapmadan ve projeyi çalıştırmadan kaydedince proje için seçtiğim klasörün içinde bin, My Project ve obj adında 3 klasör hazırlandı. Ayrıca projeye ait klasörde projenin ilk formu için 3 ve projeyle ilgili 4 dosya hazırlandı. Proje çalıştırıldığında veya derlendiğinde bin ve obj klasörlerine yeni dosyalar yerleştirilmektedir.
Burada öncelikle dikkatinize sunmak istediğim My Project klasörü ve içerdiği dosyalardır. Çünkü projenin yapılandırması bu klasördeki dosyalar aracılığı ile yapılmaktadır. Aşağıda verilen ekran görüntüsünden tespit edebileceğiniz gibi Visual Studio projeyle ilgili olarak bu klasöre toplam 7 dosya yerleştirmektedir.
Bu klasördeki Resource ön adlı 2 dosya projenin resim ve ses gibi kaynaklarıyla ilgidir. Resource dosyaları hakkında bilgiyi kitabın ilgili bölümde bulabilirsiniz. Settings ön adlı 2 dosya, projenin renk, font, dil vs. gibi özelliklerinin yapılandırmasıyla ilgilidir.
Bu bölümde asıl üzerinde durmak istediğim dosyalar Application ön adlı 2 dosyadır. “Application.myapp” adlı dosya XML formatlı bir dosya olup projenin başlangıç formunun seçilmesi ve birkaç ayar içermektedir. Project Properties penceresinden yararlanıp projenin başlangıç formunu değiştirmeniz halinde Visual Studio geri planda Application.myapp dosyasında değişiklik yapmaktadır. Doğrusunu söylemek gerekirse bu dosyayla ilgilenmeden usta işi Visual Basic uygulamaları geliştirmek mümkündür. Bu kitabı kaleme alırken sürekli olarak işin geri planını da anlatmayı tercih ettiğim için yerli yabancı yazarlardan farklı olarak bu dosya üzerinde ziyadesiyle durdum.
Windows Forms Application şablonu ile hazırlanan Visual Basic projeleri için Visual Studio’nun otomatik olarak hazırladığı ve işlevini bu bölümde anlatmak istediğim Application.Designer.vb dosyasının içeriğini aşağıda görebilirsiniz. Application.Designer.vb dosyasını açarken Not Defterinden yararlanabilirdim.
Visual Studio, XML tabanlı Application.myapp dosyasının içeriğine bağlı olarak Application.Designer.vb dosyasını güncellemektedir. Başka bir deyişle Project Properties penceresinden yararlanıp veya doğrudan Application.myapp dosyasının içeriğinde değişiklik yaptığınızda bu değişikliklerden Application.Designer.vb dosyası kendiliğinden etkilenmektedir. Sanırım neden bu 2 dosyanın içeriğini arka akaya verdiğim anlaşılmıştır.
Application.Designer.vb ve Application.myapp dosyasının içeriği ayrıca Project Properties penceresinde Application sekmesinde yapılan ayarlamalardan etkilenmektedir. Aşağıda verdiğim ekran görüntüsünü kitapta kullanmadım. Çünkü burada sayfa sıkıntısı yoktur. Tabi ki bu ekran görüntüsünde görülen bütün seçeneklerden bu bölümde söz etmeyeceğim.
Yukarıda verilen kod dosyasının içeriğini dikkatlice incelerseniz My adında bir namespace’in ve bu namespace’in içinde MyApplication adında bir Class’ın hazırlandığını görebilirsiniz. MyApplication sınıfıyla ilgili olarak dikkatinize sunmak istediğim önemli bir nokta var:Application.Designer.vb adlı kod dosyası dahilinde hazırlanan MyApplication sınıfı Microsoft.VisualBasic.ApplicationServices adlı namespace’teki WindowsFormsApplicationBase sınıfının mirasçısıdır.
Visual Studio ile hazırlanan C# uygulamalarında uygulamanın Windows’la ilişkisi Application sınıfı üzerinden kurulurken Visual Basic uygulamalarında bu ilişki WindowsFormsApplicationBase sınıfının mirasçısı MyApplication adı verilen sınıf üzerinden kurulmaktadır. Bu kodda yapılan işlemleri kolay anlatabilmek için kodun debug edilmesiyle ilgili 2 satırı sildim.
Namespace My Partial Friend Class MyApplication Public Sub New() MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.AuthenticationMode.Windows) Me.IsSingleInstance = False Me.EnableVisualStyles = True Me.SaveMySettingsOnExit = True Me.ShutdownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses End Sub Protected Overrides Sub OnCreateMainForm() Me.MainForm = Global.Proje1.Form1 End Sub End Class End Namespace
Bu kodu incelerken bir taraftan bu kitabın Konsol Uygulamaları adlı bölümde yazılanları hatırlamanızı istiyorum. Konsol uygulamaları hakkında bilgi verilen bölümde sıkça sözü edildiği gibi Visual Basic uygulamaları Sub tipi yani geriye değer göndermeyen Main() metodundan itibaren çalışmaya başlıyorlardı.
Visual Studio ile gelen Windows Forms Application şablonu ile hazırlanan bu projedeki bütün kod dosyalarını tek tek inceleseniz bile Main() metodunun olmadığını fark ederseniz. Çünkü Visual Basic projelerinde programcı kendi özel başlangıç metodunu hazırlayabilmektedir. Bunu yaparken WindowsFormsApplicationBase sınıfının mirasçısı bir sınıf hazırlamak gerekmektedir. Bu sınıfta ise Main() adında bir metot olmadığı için Windows Forms Application şablonu ile hazırlanan projelerde Main() metodu yoktur.
Yukarıda içeriği verilen XML tabanlı Application.myapp dosyasını incelediğinizde <MySubMain>true</MySubMain> gibi bir satırın olduğunu görürsünüz. Bu satırdaki true’yu false yapıp dosyanın son halini kaydetmeniz halinde Visual Studio Application.Designer.vb dosyasındaki bütün satırları siler ve bu dosyanın içeriği aşağıdaki gibi olur. Dosyadan silinmeyen bu 2 satırın değişken tanımlama şekliyle ilgili olduklarını bütün Visual Basic’çiler bilir.
Bu konuda yani <MySubMain>true</MySubMain> satırıyla ilgili olarak ek açıklama yapmak gerekirse şunlar söylenebilir:Programcı Application.myapp dosyasındaki <MySubMain> anahtarını false yapmakla Visual Studio’nun yardımıyla projesi için özel başlangıç noktası hazırlamaktan vazgeçmiş olmaktadır. Visual Basic uygulamaları için özel başlangıç noktası WindowsFormsApplicationBase sınıfının mirasçısı sınıf sayesinde hazırlandığı için bu anahtar false yapıldığında Visual Studio’nun “MyApplication” adını verdiği sınıfla ilgili bütün satırlar silinmektedir.
Başka bir deyişle programcı Visual Studio’nun WindowsFormsApplicationBase sınıfının mirasçısı sınıf sayesinde sunduğu imkanlardan vazgeçmiş olur. Bu durumda Project Properties penceresinde Startup Object liste kutusunda ayarlama yapılmazsa hata meydana gelir. Başka bir anlatımla programcı Application.myapp dosyasındaki <MySubMain> anahtarını false yaparsa gidip Project Properties penceresinde Startup Object liste kutusunda ayarlama yapmalıdır. Buna göre projede Windows formları varsa başka herhangi bir hazırlık yapmadan istediğiniz formu başlangıç formu olarak seçebilmektesiniz.
Bu yazdıklarım daha önce C#’la az çok ilgilenmiş olanları şaşırtmış olabilir. Hemen ekleyelim: C# uygulamalarının başlangıç noktasının ayarlanma şekli Delphi’den kopyadır. Zira C#’ı geliştiren ekip daha önce Borland’ın namı hesabına Delphi’yi geliştirmişti. Bu arada Visual Studio’nun C# programcılarına projelerin başlangıç formunu seçme konusunda yardımcı olmadığını belirtelim.
Burada öncelikli amacım Windows Forms Application şablonu ile hazırlanan projeler için Visual Studio’nun geri planda neler yaptığını anlatmak olduğundan Application.myapp’deki <MySubMain>true</MySubMain> anahtarını tekrar true yaptım. Uygulama için Visual Studio’nun özel başlangıç noktası hazırlamasını istemiyorsanız yukarıda yapıldığı gibi Application.myapp dosyasındaki <MySubMain> anahtarını false yapmak yerine Project Properties penceresinde Enable application framework onay kutusunu pasif duruma getirebilirsiniz.
Application.Designer.vb dosyasını yakından incelediğinizde MyApplication class’ı içinde New ve OnCreateMainForm adında 2 metodun olduğunu görürsünüz. Bu şartlarda projenin başlangıç noktası önce New() sonra OnCreateMainForm() metodudur. Başka bir deyişle proje çalıştırıldığında ilk olarak Application.Designer.vb dosyasındaki MyApplication adı verilen class’ının New() metodu işletilir. Devamında sıra OnCreateMainForm() metoduna gelir. OnCreateMainForm() metodu WindowsFormsApplicationBase sınıfı kaynaklı olduğu için Override edilmektedir.
Application.Designer.vb dosyası dahilinde hazırlanan MyApplication sınıfındaki New() metodunda WindowsFormsApplicationBase sınıfının mirasçısı MyApplication sınıfının bazı özellikleri ayarlanmaktadır. Application.Designer.vb dosyasındaki New() metodunu silseniz bile proje sorunsuzca çalışmaya devam eder. Konu üzerinde düşünmenizi sağlamak için üzerinde çalıştığım projedeki Form1.vb ve Form1.Designer.vb dosyalarını Solution Explorer penceresinden yararlanarak sildim. Aşağıda verilen ekran görüntüsünü projedeki ilk formla ilgili dosyaları sildikten sonra aldım. Tabii bu şartlarda proje çalıştırılırsa hata meydana gelir.
Projenin hatasız çalışması için Application.Designer.vb dosyasındaki OnCreateMainForm metodunu aşağıdaki gibi düzenledim. My adı verilen namespace’teki MyApplication sınıfının New() metodunu silmemiş olsaydım ve MessageBox sınıfının Show() metodunu New() metoduna yazmış olsaydım yine işletilirdi. Yani Application.Designer.vb dosyasındaki New() metodunu silebilir ancak OnCreateMainForm() metodunu silerseniz proje çalışmaz.
Tahmin edeceğiniz gibi bu değişiklikten sonra proje çalıştırılırsa OnCreateMainForm() metodu dahilinde kod yazılarak hazırlanan “F1” nesnesi projenin başlangıç formu olur ve aşağıdaki gibi bir sonuçla karşılaşılır.
Tam bu noktada kitaptan alınan metne bir soru ekleyelelim:İngilizcesi çok sınırlı Memik Yanık’ı MSDN’den çeviri yapmakla suçlayanlara soralım: Bu anlatım şekli MSDN’nin neresindedir, dünyadaki hangi yazar Application.Designer.vb dosyasının içeriğiyle bu şekilde oynamıştır?
Bu şartlarda projenin başlangıç formunun bütün görsel özelliklerini kendim ayarlamak ve olaylarını temsil edecek metotları kendim hazırlamak zorundayım. Madem Visual Studio her türlü kolaylığı bize sağlıyor deneysel amaçlar hariç projenin başlangıç formunu hazırlarken veya seçerken Visual Studio’dan yararlanmak gerekir.
Konu üzerinde düşünmenizi sağlamak için yukarıda Application.Designer.vb dosyasını değiştirdiğim projeyi silip aynı ada sahip 2. bir proje hazırladım. Ardından bu yeni projenin Application.Designer.vb dosyasını aşağıdaki gibi düzenledim.
Ekran görüntüsü büyük olmasın diye New() metodunu sildim. Madem projenin başlangıç noktası bu şartlarda OnCreateMainForm() metodudur, bu metotta projedeki “Form1” nesnesi projenin başlangıç formu olarak ayarlanmadan önce bu metoda yazdığım satır işletilir. Başka bir deyişle bu proje çalıştırılırsa ekrana önce MessageBox sınıfı sayesinde projenin başlatılacağını haber veren bir diyalog kutusu gelir. Bu diyalog kutusu kapatıldığında ise bu kez MyApplication sınıfının MainForm özelliğine adı aktarılmış form ekrana gelir.
Yukarıda yazılanları tekrar etmek gerekirse; Visual Studio ile Windows Forms Application şablonu kullanılarak Visual Basic projesi hazırlandığı zaman Visual Studio tarafından otomatik olarak Application.myapp ve Application.Designer.vb adında 2 dosya hazırlanmaktadır. Project Properties penceresinde Application sekmesinde yapılan ayarlamalar Visual Studio tarafından otomatik olarak XML tabanlı Application.myapp dosyasına, Application.myapp'de yapılan değişiklikler ise Application.Designer.vb dosyasına yansıtılmaktadır.
Özel durumlar hariç bu 2 dosya ile ilgilenmenize gerek yoktur. Application.Designer.vb dosyasındaki OnCreateMainForm metodunda başlangıç formunun seçilmesi ile birlikte Form1 sınıfını temsil eden kod işletilmiş olunuyor.
Formlar İçin Hazırlanan Kodlar
Şimdi sırada Visual Studio tarafından projedeki her form için hazırlanan kodları incelemek var. Daha önceki konulardan bildiğiniz gibi Visual Studio ile hazırlanan projelere dahil edilen her form 2 kod dosyası ile temsil edilmektedir. Form1.vb dosyasında genellikle programcının yazdığı kodlar olurken Form1.Designer.vb dosyasında formun görsel yapısı ile ilgili satırlar olmaktadır. Programcı formun görsel özelliklerini Properties penceresinden veya fareden yararlanarak ayarladığında Visual Studio otomatik olarak Form1.Designer.vb dosyasında değişiklik yapmaktadır. Bu nedenle projedeki ilk formu temsil eden “Form1.vb” dosyasında başlangıçta yalnızca Class deklarasyonu olmaktadır.
Bu şartlarda yani projenin başlangıç formu olarak kullanılan forma kaynaklık eden “Form1” sınıfının diğer yarısı Form1.Designer.vb dosyasında olmaktadır. Derleme sırasında bu 2 dosyadaki kodların birleştirildiğini biliyorsunuz. Aşağıda verilen kodun projeye dahil edilen her form için Visual Studio tarafından otomatik olarak hazırlandığını biliyorsunuz(tabii bu yorumu Visual Basic 9.0 kitabımı okuyanlar için yaptım. Yoksa başka kaynaklarda bu dosyanın içeriğiyle pek ilgilenilmez).
Bu kodu yakından incelediğinizde Dispose ve InitializeComponent() adında 2 metodun olduğunu fark edersiniz. Dispose metodu, System.Windows.Forms’de yer alan Form sınıfı kaynaklı olduğu için Override edilmektedir. Hemen eklemek isterim:Bu projeyi hazırladıktan hemen sonra projenin başlangıç formunun boyutlarında veya başka bir özelliğinde değişiklik yapsaydım InitializeComponent() metodunda daha fazla satır olurdu.
Bu koddaki DebuggerStepThrough adlı attribute bu kod debug edilirken veya kod adım adım işletilirken InitializeComponent metodunun devre dışı bırakılmasını sağlamaktadır. Bu nedenle DebuggerStepThrough ve DebuggerNonUserCode adlı niteliklerin kullanıldığı satırları silebilirsiniz.
Visual Studio tarafından otomatik olarak hazırlanan bu koddaki Dispose() metodu tahmin edebileceğiniz gibi form nesnesinin sonradan bellekten silinmesiyle ilgilidir. Bu nedenle bu koddan Dispose metodunu silseniz bile proje hatasız çalışır. Tabi büyük projelerde çok sayıda form açılıp kapatılacağı için bellek israfı olur. Buradaki amacımız deneysel olduğu için Dispose() metodunu sildim.
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _ Partial Class Form1 Inherits System.Windows.Forms.Form Private components As System.ComponentModel.IContainer Private Sub InitializeComponent() components = New System.ComponentModel.Container() Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font Me.Text = "Form1" End Sub End Class
Bu kodda en basit anlatımla System.Windows.Forms.Form sınıfının mirasçısı “Form1” adında bir Class hazırlanmaktadır. Inherits System.Windows.Forms.Form satırı ile “Form1” adı verilen sınıfın System.Windows.Forms adlı .NET Framework ile gelen namespace’teki Form sınıfının mirasçısı olduğu işaret edilmektedir. Bu Class’ın InitializeComponent() adında bir metodu bulunmaktadır. Bu metotta Form1 adlı Class’ın bazı özellikleri ayarlanmaktadır. Başlangıçta bu metotta Form1 class’ının yalnızca Text ve AutoScaleMode özellikleri ayarlanmaktadır.
Bu Class’ın ayrıca componets adında ve System.ComponentModel.IContainer tipinde bir alanı bulunmaktadır. InitializeComponent() metodu içinde bu alan yani nesne oluşturulmaktadır. Dispose işlemi hakkında bilgi verilen bölümde “components” adı verilen nesnenin işlevinden söz edilecektir. Bu arada Memik Yanık karşıtlarına bir soru soralım: Şimdiye kadar incelediğiniz Visual Basic ve C# konulu hangi kaynakta “components” adlı nesnenin işlevinden söz ediliyordu?
Form1 sınıfı için Visual Studio tarafından hazırlanan Form1.Designer.vb dosyasında asıl dikkatinize sunmak istediğim DesignerGenerated niteliğidir. Bu nitelik sayesinde forma yerleştirilen kontroller tasarım anında görülebilmektedir. DesignerGenerated niteliğinin işletildiği satırı silerseniz proje çalıştırıldığında InitializeComponent metodu işletilmez ve forma yerleştirilen nesneler görünmez. Daha sonra değinileceği üzere Visual Basic’te nitelikler, metotlara veya class’lara uygulanırken “<>” arasına yazılmaktadır.
MyApplication Sınıfının Olayları
Yukarıdaki sayfalarda işaret edildiği gibi Visual Studio ile yeni bir proje hazırlandığı zaman Application.Designer.vb adlı kod dosyasında MyApplication adında bir sınıf hazırlanmaktadır. Bu sınıf WindowsFormsApplicationBase sınıfının mirasçısı olduğundan çok sayıda olaya, metoda ve özelliğe sahiptir. Yukarıda verilen koddan hatırlayacağınız gibi Visual Studio, WindowsFormsApplicationBase’den miras alınan OnCreateMainForm metodunu override edip projenin başlangıç formunun seçilmesine imkan sağlamaktadır. Ayrıca Project Properties penceresinde proje için SplashScreen seçildiğinde ise Visual Studio tarafından Application.Designer.vb dosyasında WindowsFormsApplicationBase sınıfı kaynaklı OnCreateSplashScreen metodu override edilip hangi formun açılış formu olarak kullanılacağı ayarlanmaktadır. MyApplication sınıfının WindowsFormsApplicationBase’den miras alınan özellik, olay ve metotlarından yararlanırken Visual Studio’nun size yardımları bu 2 metodun override edilmesi ile sınırlı değildir. Şimdi MyApplication sınıfının OnShutdown olayı için kod yazacağım. Bu olayı temsil eden metoda yazacağım satır ile kullanıcıya uygulamanın çalışmasının sona ereceğini önceden haber vereceğim. Bu amaçla Project menüsünden komut verip Project Properties penceresini ekrana getirdim.
Bu ekran görüntüsünü incelerseniz Application sekmesinde View Application Events başlıklı bir düğmenin olduğunu farkedersiniz. Bu düğme tıklandığında Visual Studio tarafından Windows Forms Application’ler için otomatik olarak hazırlanan MyApplication sınıfının WindowsFormsApplicationBase kaynaklı olayları için kod yazabilesiniz diye “ApplicationEvents.vb” adında bir kod dosyası hazrlanıp bu dosya açılmaktadır. Aşağıda verilen ekran görüntüsünü düğmeyi tıkladıktan sonra aldım.
Her ne kadar MyApplication sınıfının olayları için kod yazabilmeniz için Visual Studio ayrı bir dosya hazırlamış olsa bile MyApplication sınıfı partial bir sınıf olduğu için derleme sırasında ApplicationEvents.vb ile Application.Designer.vb dosyaları birleştirilmektedir. Application.Designer.vb dosyasında fazla satır yoksa veya ayrı bir kod dosyası hazırlamaya gerek yok diyorsanız MyApplication sınıfının olayları için kod yazma işlemine Project Properties penceresindeki View Application Events düğmesini tıklamak yerine mevcut Application.Designer.vb dosyasını açıp Class Name liste kutusundan yararlanabilirsiniz. Aşağıda verdiğim ekran görüntüsünü almadan önce View Application Events düğmesini tıkladığım için Visual Studio tarafından hazırlanan “ApplicationEvents.vb” dosyasını Solution Explorer penceresinden yararlanarak sildim.
Application.Designer.vb dosyasın açıldığı kod penceresindeki Class Name liste kutusunda başlangıçta yalnızca MyApplication sınıfı listelenmektedir. Bu sınıfla ilgili MyApplicationEvents seçeneğini seçerseniz kod penceresindeki Method Name adlı diğer liste kutusunda MyApplication sınıfının olayları listelenir. Bu olayları aşağıda verdiğim ekran görüntüsünde görebilirsiniz.
Hangi olay için metot hazırlamak istiyorsanız Method Name liste kutusunda o olayı seçmeniz gerekir. Verilen ekran görüntüsünden tespit edebileceğiniz MyApplication sınıfının toplam 5 olayı bulunmakta ve bu olaylar WindowsFormsApplicationBase sınıfı kaynaklıdır. Method Name liste kutusunda ShutDown olayını seçince “ApplicationEvents.vb” dosyasında Visual Studio aşağıdaki gibi bir metot hazırladı.
Private Sub MyApplication_Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shutdown MessageBox.Show("Uygulama kapatılacak") End Sub
Bu metotta daha çok uygulama kapatılmadan önce yapılması istenen işlemler tamamlanır. Burada ShutDown olayını temsil eden metotta MessageBox sınıfının Show() metoduna yer verdiğim için uygulamanın çalışması sona erdirilmek istendiğinde kullanıcıya mesaj verilir.
WindowsFormsApplicationBase Sınıfı
Şimdiye kadar bu bölümde Visual Studio ile hazırlanan Visual Basic uygulamaları hakkında yazılanlara bakılırsa uygulamaların başlangıç noktası Microsoft.VisualBasic.ApplicationServices’deki WindowsFormsApplicationBase sınıfının mirasçısı bir sınıf tarafından hazırlanmaktadır. Uygulamanın başlangıç noktası olarak kullanılan bu sınıfa MyApplication adı verilmekte ve bu sınıf Visual Studio’nun My adını verdiği bir namespace’e konulmaktadır.
Visual Studio tarafından hazırlanan Visual Basic uygulamalarıyla ilgili olarak geri planda nelerin olduğunu hiç merak etmeden usta işi programlar yazmak mümkündür. Bu nedenledir ki Visual Studio başlangıçta MyApplication adını verdiği sınıfla ilgili kod dosyalarını Solution Explorer penceresinde gizlemektedir. Ötesi bu bölümde anlatılan bir çok konunun yerli yabancı başka kitaplarda bulunması ihtimali düşüktür. Şimdi gelin konuyu baştan alalım ve Visual Studio ile gelen Windows Forms Application şablonunu kullanarak bir Visual Basic uygulaması hazırlayalım. Tahmin edeceğiniz gibi Visual Studio, bu şablon ile hazırlanan uygulamaya “Form1” adında bir form dahil edip Application.Designer.vb dosyasında MyApplication adında bir sınıf hazırlamaktadır. Visual Studio’dan bu konuda yardım almak istemediğim için Project Properties penceresini ekrana getirip Enable application framework onay kutusunu pasif duruma getirdim.
Project Properties penceresinde bu onay kutusu pasif duruma getirildiği zaman Application.Designer.vb dosyası silinmese bile içeriği temizlenmektedir. Başka bir deyişle Visual Studio tarafından hazırlanan MyApplication sınıfıyla ilgili satırlar silinmektedir. Aşağıda verilen ekram görüntüsünü “Enable application framework” onay kutusunu pasif duruma getirdikten sonra aldım.
Bu şartlarda Visual Studio ile hazırlanan Visual Basic uygulamasının başlangıç noktası belli olmadığı için proje çalışırılırsa hata meydana gelir. Ötesi bu onay kutusu pasif duruma getirilirse programcı WindowsFormsApplicationBase sınıfı ile sunulan imkanlardan yararlanmamayı tercih etmiş olur. Çünkü konu Visual Basic uygulamaları olduğunda Visual Studio programcıya bir çok kolaylık sağlamaktadır.
Her ne kadar Visual Studio projenin başlangıç formunu seçme konusunda programcıya zorluk çıkarmasa bile başka teknikler de yok değildir. Örneğin mevcut VB uzantılı kod dosyalarının birisinde Main() metodu hazırlanıp ondan sonra Project Properties penceresinde Startup object liste kutusuna ayarlama yapılabilir.
Tabi bu uygulama bir Windows Forms uygulaması olduğunda başlangıç formu için bir takım işlemlerin yapılması gerekmektedir. Yoksa projenin başlangıç formu Show() veya ShowDialog() metodu ile ekrana getirilse bile Windows’tan uygulamaya gönderilen mesajlar yakalanamaz. Bu sorunun birden fazla çözümü var:En zahmetsiz çözüm uygulamanın başlangıç formunun örneğini Application sınıfının Run() metoduna parametre olarak vermektir. Konsol uygulamaları adlı bölümde bu yöntemden söz edilmişti. Belki bazılarına garip gelmiştir ve Memik Yanık kitabının konsol uygulamaları adlı bölümünde ekrana neden form getirmektedir sorusunu sormuşlardır.
İkinci çözüm yani Visual Basic uygulaması ile Windows arasında ilişki kurarken ApplicationContext sınıfından yararlanmaktır. Bu bölümün ileriki sayfalarında ApplicationContext sınıfı hakkında bilgi verilecektir. Hemen bir ekleme yapalım: C++ ile Windows uygulaması geliştirenler uygulama ile Windows’un ilişkisinden bir haber değillerdir. Windows Forms uygulaması ile Windows arasında ilişki kurmak için tercih edilecek üçüncü yöntem WindowsFormsApplicationBase sınıfının mirasçısı bir sınıf hazırlamaktır. Visual Basic uygulamaları için Visual Studio tarafından tercih edilen yöntem budur. Visual Studio’dan destek almadan bu sınıftan nasıl yararlanıldığını anlatmak için Application.Designer.vb dosyasını aşağıdaki gibi düzenledim.
Bu sınıfı Visual Studio tarafından hazırlanan Application.Designer.vb dosyası yerine başka bir kod dosyasında kodlayabilirdim. Olur ya bu kod dosyasında yukarıda yaptığım gibi kodlama yapıp sonrada Project Properties penceresinde Enable application framework onay kutusunu pasif duruma getirir veya Applicatiıon.myapp dosyasındaki <MySubMain> anahtarını True yaparsanız Visual Studio yazdıklarınızı siler. Bu nedenle C# uygulalarından kopya çekip “Program.vb” adında bir kod dosyası hazırlayıp yukarıda verdiğim MyApplication sınıfıyla ilgili satırları bu dosyaya taşıdım. Ayrıca kod satırları kısa olsun diye Imports deyimi ile Microsoft.VisualBasic.ApplicationServices’deki sınıflardan yararlanmak istediğimi belirttim.
Microsoft.VisualBasic.ApplicationServices’deki WindowsFormsApplicationBase sınıfının mirasçısı bu sınıfa Visual Studio gibi MyApplication adını vermiş olsam bile sizler istediğiniz adı verebilirsinz. WindowsFormsApplication sınıfının mirasçısı bu sınıfın gövdesini hazırladıktan sonra ilk olarak OnCreateMainForm metodunu override edeceğim. Çünkü bu metotta uygulamanın başlangıç formu seçilmektedir. Hangi formun uygulamanın başlangıç formu olmasını istiyorsanız bu formun adını WindowsFormsApplicationBase sınıfının mirasçısı sınıfın MainForm özelliğine aktarmalısınız. Bu işlemi nasıl yaptığımı aşağıda görebilirsiniz.
Imports Microsoft.VisualBasic.ApplicationServices Public Class MyApplication Inherits WindowsFormsApplicationBase Protected Overrides Sub OnCreateMainForm() Me.MainForm = Proje1.Form1 End Sub End Class
Başlangıç formu olarak Visual Studio’nun projeye dahil ettiği ilk formu kullanmak istediğim için böyle bir düzenleme yaptım. Bu sınıfın override edilecek başka metotları ve kendisi için metot hazırlanabilinecek birkaç olayı olsa bile şimdilik bu kadarıyla yetindim. “Program.vb” adını verdiğim kod dosyasında MyApplication adını verdiğim sınıfı bu şekilde hazırladıktan sonra bu kod dosyasında Main() metoduna yer verdim. Main() metodu ile WindowsFormsApplicationBase sıfının mirasçısı sınıfın aynı kod dosyasında olması şart değildir. Main() metodunu ayrı bir Class veya modüle dahil etmek gerekeceğini tahmin etmiş olmalısınz.
Şimdi sırada WindowsFormsApplicationBase sıfının mirasçısı sınıfın örneğini almak var. Bu amaçla “Program” adını verdiğim sınıftaki(sizler başka adlar verebilirsiniz) Main() metodu içinde bu sınıfın örneğini aşağıdaki gibi aldım.
Public Class Program Shared Sub Main() Dim baslangic As MyApplication baslangic = New MyApplication() End Sub End Class
Sırada WindowsFormsApplicationBase sıfının mirasçısı sınıfın örneğinin Run() metodunu kullanmak var. Main() metodu içinde WindowsFormsApplicationBase sınıfı kaynaklı Run metodunu kullanabilmek için Main() metodunun parametreli olması gerekmektedir. Bu nedenle Main() metodu için string tipte bir dizi değişkeni parametre olarak kullandım.
Public Class Program Shared Sub Main(ByVal args() As String) Dim baslangic As MyApplication baslangic = New MyApplication() baslangic.Run(args) End Sub End Class
Bu hazırlıklardan sonra proje çalıştırıldığında bu Main() metodunun projenin başlangıç noktası olabilmesi için Project Properties penceresinde Startup Object liste kutusunda Main() metodunun olduğu sınıfın adı seçilmelidir(burada bu sınıfa “Program” adını vermiştim).
Yukarıda işaret edildiği gibi Visual Studio ile hazırladığınız Visual Basic uygulamasında bir veya birden fazla form varsa Applicatiıon.myapp dosyasındaki <MySubMain> anahtarı ister True ister false olsun Project Properties penceresinde Startup Object liste kutusunda formun birisi seçildiğinde uygulama o formdan başlıyor. Bu durumda Visual Studio tarafından hazırlanan WindowsFormsApplication sınıfının mirasçısı bu sınıfla neden ilgilenmek gerekiyor diye sorabilirsiniz. Visual Studio’nun otomatik olarak hazırladığı MyApplication sınıfı ile yapılan işlemlere örnek olması için Splash form hazırlayacağım. Bu amaçla üzerinde çalıştığım projeye 2. bir form dahil ettim ve bu forma “splash_form” adını verdim. Ardından “Program.vb” adını verdiğim kod dosyasındaki WindowsFormsApplicationBase sınıfının mirasçısı sınıfta OnCreateSplashScreen metodunu aşağıdaki gibi override ettim.
Imports Microsoft.VisualBasic.ApplicationServices Public Class MyApplication Inherits WindowsFormsApplicationBase Protected Overrides Sub OnCreateMainForm() Me.MainForm = Proje1.Form1 End Sub Protected Overrides Sub OnCreateSplashScreen() Me.SplashScreen = Proje1.splash_form End Sub End Class
Bu hazırlıktan sonra proje çalıştırılırsa öncelikle adı WindowsFormsApplicationBase sınıfının mirasçısı sınıfın SplashScreen özelliğine aktarılan form ekrana getirilir. Bu form ekranda kısa bir süre durduktan sonra ekrana bu kez adı MainForm özelliğine aktarılan form gelir.
WindowsFormsApplicationBase sınıfının mirasçısı sınıf sayesinde Visual Basic uygulamanızı yapılandırırken Visual Studio’dan yararlanmayı tercih ettiyseniz, başka bir deyişle Application.myapp dosyasındaki <MySubMain> anahtarını True yaptıysanız Splash form seçimini Project Properties penceresinde yapabilirsiniz. Splash Screen liste kutusunda seçilen forma göre Visual Studio geri planda Application.Designer.vb dosyasındaki MyApplication sınıfında OnCreateSplashScreen() metodunu override eder.
Her ne kadar yukarıda WindowsFormsApplicationBase sınıfı kaynaklı olaylardan az çok söz etmiş olsam bile Visual Basic uygulamasını yapılandırırken Visual Studio’dan yararlanmama yolunu tercih edenler için yukarıda hazırladığım sınıfın birkaç olayından söz edeceğim. Bu amaçla ilk olarak aşağıdaki basit bir metot hazırladım.
Imports Microsoft.VisualBasic.ApplicationServices Public Class MyApplication Inherits WindowsFormsApplicationBase Protected Overrides Sub OnCreateMainForm() Me.MainForm = Proje1.Form1 End Sub Protected Overrides Sub OnCreateSplashScreen() Me.SplashScreen = Proje1.splash_form End Sub Private Sub Uygulama_Baslatma(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Startup MessageBox.Show("Uygulama Başlatıldı") End Sub End Class
Bu ayarlamadan sonra proje başlatılırsa Splash form ile birlikte Show metodu ekrana bir diyalog kutusu getirilir. Bu diyalog kutusu kapatıldığında Splash Form kapatılıp uygulamanın asıl formu ekrana getirilir. Çünkü Handles deyimiyle bu metodun bu sınıfın StartUp olayını temsil etmesini sağladım. “Uygulama_baslatma” adını verdiğim metotla bu sınıfın StartUp olayını ilişkilendirirken AddHandler deyiminden yararlanabilirdim. Bu amaçla aşağıda verdiğim satırı OnCreateMainForm metoduna yazabilirsiniz.
AddHandler Me.Startup, AddressOf Me.Uygulama_Baslatma
Şimdi ise WindowsFormsApplicationBase sınıfı kaynaklı OnRun() metodunu override edeceğim. Bu amaçla yukarıda verdiğim sınıfı aşağıdaki gibi düzenledim. Bu şartlarda bu sınıfın örneği alınıp Run() metodu işletildiğinde önce OnRun, ardından OnCreateMainForm metodu işletilir.
Imports Microsoft.VisualBasic.ApplicationServices Public Class MyApplication Inherits WindowsFormsApplicationBase Protected Overrides Sub OnCreateMainForm() Me.MainForm = Proje1.Form1 End Sub Protected Overrides Sub OnRun() MyBase.OnRun() End Sub End Class
Bu şartlarda OnRun() metodunun varlığı ile yokluğu birdir. Çünkü bu metodun orijinali zaten böyledir. Şimdi konu üzerinde düşünmenizi sağlamak için bu metoda bir satır ekleyeceğim.
Imports Microsoft.VisualBasic.ApplicationServices Imports System.Windows.Forms Public Class MyApplication Inherits WindowsFormsApplicationBase Protected Overrides Sub OnCreateMainForm() Me.MainForm = Proje1.Form1 End Sub Protected Overrides Sub OnRun() MyBase.OnRun() MessageBox.Show("Uygulama çalışmaya başladı") End Sub End Class
OnRun() metodunu bu şekilde değiştirip proje çalıştırılırsa doğal olarak MyBase.OnRun() satırı sayesinde uygulama başlatılır. Tabii sıranın MessageBox sınıfının kullanıldığı satıra gelmesi için uygulamanın çalışmasının sona erdirilmesi gerekir. Tahmin edeceğiniz gibi bu metottaki MyBase.OnRun satırı silinirse uygulama çalışmaz. WindowsFormsApplicationBase sınıfı kaynaklı OnRun() metodu uygulama çalışmaya başladıktan sonra işletilmektedir. Bu sınıfın ayrıca OnStartUp adında bir metodu vardır. Kendi hazırladığım sınıfta bu metodu aşağıdaki gibi Override ettim.
Imports Microsoft.VisualBasic.ApplicationServices Imports System.Windows.Forms Public Class MyApplication Inherits WindowsFormsApplicationBase Protected Overrides Sub OnCreateMainForm() Me.MainForm = Proje1.Form1 End Sub Protected Overrides Sub OnRun() MessageBox.Show("Uygulama çalışmaya başladı") MyBase.OnRun() End Sub Protected Overrides Function OnStartup(ByVal eventArgs As _ Microsoft.VisualBasic.ApplicationServices.StartupEventArgs) _ As Boolean MessageBox.Show("Uygulama çalışmaya başlayacak") Return MyBase.OnStartup(eventArgs) End Function End Class
Bu şartlarda uygulama çalıştırılırsa önce OnStartup, ardından OnRun() metodu işletilir. OnRun() metodundan sonra sıra OnCreateMainForm metoduna gelir. OnCreateMainForm metodundan sonra sıra başlangıç formunun Load olayını temsil eden metoda gelmektedir.
Application Sınıfı
Bu kitabın bazı bölümlerinde yer yer sözü edilmekle birlikte şimdiye kadar Application sınıfı hakkında derli toplu bilgi verilmedi. Kitabın sayfa sayısını fazla arttırmamak için bu bölümde Application sınıfının temel özelliklerinden ve metotlarından söz etmekle yetineceğim. Bu kitabın sayfa sayısını azaltmak için önce bazı ekran görüntülerini çıkardım. Sonra her kaynakta bulunan bazı konuları devre dışı bıraktım. En son olarak kitabın kenar boşluklarını azaltma yoluna gittim. Buna rağmen kitap yaklaşık 1100 oldu. Tabi kitap 1100 olunca fiyatı yüksek oldu. Bu durumda az sayfaya sahip ve son derece kısıtlı içeriğe sahip kitaplar düşük fiyatları nedeniyle daha çok tercih edildi. Ne yapalım; bu kitapta hedefim en kapsamlı Visual Basic kitabını yazmaktı.
Application ve WindowsFormsApplicationBase sınıflarıyla hiç ilgilenmeden profesyonel kalitede programlar yazmak mümkündür. Bu nedenledir ki birçok yerli yabancı kaynakta Application sınıfından hiç söz edilmez ya da birkaç cümle ile geçiştirilir. Tabii Application sınıfının mutlaka gerek duyulan bir kaç metodundan söz edilir ama bu söz etmede Application sınıfına vurgu yapılmaz. Örneğin uygulamanın çalışması sona erdirilirken gerek duyulan Exit() metodundan bir cümle ile söz edilir. Anlatılmak istenen uygulamanın çalışmasını sona erdirmek ise, Exit() metodunun nasıl kullanıldığını göstermek yeterli olmaktadır. Bu kısımda asıl amacım Application sınıfı hakkında yazılanların anlaşılması olduğu için zaman zaman pratik değeri olmayan bazı işlemler yapılıp üzerinde konuşuldu.
Daha önce namespace’ler hakkında bilgi verilen bölümde işaret ettiği gibi Visual Studio tarafından Visual Basic projeleri için otomatik olarak hazırlanan My adlı namespace’te birkaç class bulunmaktadır. Bu class’lardan yararlanarak bir çok işlemi kolayca yapmak mümkündür. My adlı namespace’te hazırlanıp kullanıma sunulan sınıflardan birisi Application’dır. Aşağıda verilen ekran görüntüsünden tespit edeceğiniz gibi My’deki Application sınıfı çok sayıda metoda ve özelliğe sahiptir.
Örneğin My’deki Application sınıfının OpenForms özelliğinden yararlanıp açık formların hangileri olduğunu öğrenebilirsiniz. OpenForms özelliğinin nasıl kullanıldığını anlatmak için 2 forma sahip bir proje hazırlayıp başlangıç formuna bir ListBox yerleştirip aşağıda verdiğim kodu yazdım.
Private Sub Listele_Click(ByVal sender As System.Object, _ ByVal e As EventArgs) Handles Listele.Click Dim sayi As Integer Dim ad As String sayi = My.Application.OpenForms.Count For i As Integer = 0 To sayi - 1 ad = My.Application.OpenForms.Item(i).Name ListBox1.Items.Add(ad) Next End Sub
My’deki Application nesnesinin OpenForms özelliği bir koleksiyon olduğu için bu koleksiyonun eleman sayısını öğrenip elemanların Name özelliklerini ListBox’a aktardım. Sonradan fark ettim; yani kitaptan aldığım bu metni gözden geçirirken yine alışkanlıklarımın kurbanı olup bu kodda Sayi ve i adında 2 Integer değişken tanımladığımı fark ettim. Bu durumda değişken adı çalma kabahatini tekrar işlemişim. Umarım sayi ve i adlı değişkenlerin sahipleri Visual Basic 9.0 kitabımı inceleyip değişken hırsızı avına çıkmazlar. Yoksa yandım…
Konu Visual Studio 2008 ile hazırlanan Visual Basic projeleri olduğunda yukarıda sözü edilen Application sınıfından başka programcıların yararlanabileceği Application sınıfı bulunmaktadır. System.Windows.Forms’de yer alan Application sınıfı çok sayıda shared metoda ve özelliğe sahiptir. System.Windows.Forms’deki Application sınıfı hakkında bilgi vermek için Visual Studio ile gelen Windows Forms Application şablonu kullanılarak hazırlanan projeyi, Visual Studio ile yine Windows Forms Application şablonu kullanılarak hazırlanan C# projesine benzetmeye çalışacağım. Bu amaçla ilk olarak My Project klasöründeki Application.myapp ve Application.Designer.vb dosyalarını sildim.
Aslında My Project klasörü içinde yer alan AssemblyInfo.vb ve diğer dosyaları da silebilirdim. Ne var ki amacım Visual Basic projesini C# projesine benzetip Application sınıfının işlevinin net olarak görülmesi olduğu için projeye Program.vb adında bir kod dosyası dahil etmekle yetindim. Çünkü Visual Studio ile hazırlanan C# projelerinde de AssemblyInfo, Resource.Designer ve Settings.Settings dosyaları bulunuyor. Visual Basic projelerindeki Application.myapp ve Application.Designer.vb dosyalarına karşılık C# projelerinde Program.cs dosyası bulunmakta ve projenin başlangıç noktası olan Main() metodu bu dosyada yer almaktadır. Aşağıda verilen ekran görüntüsünü bir C# projesinden aldım.
Visual Studio ile hazırlanan C# projeleri ile Visual Basic projeleri arasındaki en önemli fark Application.myapp dosyası(dolayısıyla Project Properties penceresi kullanılarak) aracılığı ile uygulamanın bazı özellikleri ayarlanmaktadır. Bu ayarlamalar sayesinde Visual Basic projesinin seçilen başlangıç noktası Main() metodu değildir. Visual Studio ile hazırlanan Visual Basic uygulamasının başlangıç noktası Main() metodu olmadığı için programcı Application sınıfı ile yüz yüze gelmiyor. Sonradan Visual Basic uygulamasına dahil ettiğim “Program.vb” dosyasını nasıl düzenlediğimi aşağıda görebilirsiniz.
“Program.vb” adını verdiğim bu kod dosyasında Main() metoduna yer verip Application sınıfının Run metoduna projenin başlangıç formu olan Form1’i parametre olarak verdim. Application.myapp ve Application.Designer.vb dosyalarını silip sonradan projeye eklenen kod dosyası bu şekilde düzenlense bile proje çalışmaz. Çünkü Project Properties penceresinde yeni şartlara göre başlangıç noktasının seçilmesi gerekir. Projenin başlangıç noktasının Program.vb dosyası olmasını istediğim için Project Properties penceresinde Starup object olarak Program’ı yani Program adını verdiğim class’ı seçtim.
Bu ayarlamadan itibaren Visual Basic uygulaması sorunsuz çalışır. Visual Basic projesi için hazırladığım "Program.vb" dosyasının Visual Studio’nun C# projeleri için hazırladığı “Program.cs” dosyasına biraz daha benzemesi için aşağıdaki gibi düzenledim.
Gördüğünüz gibi projenin başlangıç formunu önceden hazırlayıp Application sınıfının Run() metoduna parametre olarak verdim. Burada Main() metodundan önce kullandığım <STAThread> niteliği(attribute) ile uygulamanın nasıl bir Thread veya kanal modeline sahip olması gerektiği işaret edilmektedir. Thread’ler ya STA(Single Thread Apartment–tek kanallı) ya da MTA(Multi Thread Apartment–çok kanallı) olabilmektedir.
Visual Basic uygulamasını başlangıç formunu Application sınıfının Run() metoduna parametre olarak vermeden çalıştırmak mümkündür. Bunu size göstermek için yukarıda verdiğim “Program.vb” dosyasındaki Main() metodunu aşağıdaki gibi düzenledim.
Imports System Imports System.Windows.Forms Class Program <STAThread()> _ Shared Sub Main() Dim Form1 As New Proje1.Form1() Form1.Show() End Sub End Class
Bu kodda projedeki “Form1” adlı class’ın örneğini aldıktan sonra bu nesneyi veya formu Show() metodu ile ekrana getirdim. Bu kod sayesinde “Form1” ekrana getirilir ama ekrana getirilmesi ile kapatılması bir olur. Show() yerine ShowDialog() metodu kullanılırsa form kullanıcı tarafından kapatılana kadar ekranda kalır. Projenin ilk formunu ekrana getirmek için ShowDialog() metodunu kullanmak yerine Application sınıfının Run() metodunu işleten bir satır eklerseniz form kapatılana kadar projenin çalışması devam eder.
Shared Sub Main() Dim Form1 As New Proje1.Form1() Form1.Show() Application.Run() End Sub
Burada projenin başlangıç formu Application sınıfının Run() metoduna parametre olarak verilmediği için form kapatılsa bile Application nesnesinin çalışması devam eder. Bu şartlarda EXE dosyanın çalışmasını sona erdirmek için Windows’un Görev Yöneticisi penceresine başvurmak gerekir. Bu nedenle ya uygulamanın başlangıç formu Application sınıfının Run() metoduna parametre olarak verilmeli ya da formun FormClosing olayını temsil eden metotta Application sınıfının Exit() metodu işletilmelidir.
Private Sub Form1_FormClosing(ByVal sender As Object, _ ByVal e As FormClosingEventArgs) Handles MyBase.FormClosing Application.Exit() End Sub
Ötesi başlangıç formunu önce Show() metodu ile ekrana getirip sonra da Application’ı Run() metodu ile başlatırsanız açacağınız ikinci veya üçüncü formlar birbirinden bağımsız olur. Bu nedenle çok özel durumlar söz konusu değilse başlangıç formunu Run() metoduna parametre olarak vermeniz önerilir. Application sınıfından yardım almak istemiyorum deyip Show() metodu ile ekrana getirdiğiniz formun Windows’la ilişkisini kendim kuracağım derseniz durum değişir.
System.Windows.Forms’da tanımlı Application sınıfı çok sayıda özellik ve metoda sahiptir. Bazen uygulamayı yeniden başlatma gereğini duyabilirsiniz. Application sınıfının Restart() metodu uygulamayı kapatıp tekrar çalıştırmaktadır. Başka bir deyişle Restart() metodu devam eden işlemleri sonlandırıp tekrar başlangıç formunun Load olayını temsil eden metodu işletmektedir.
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Application.Restart() End Sub
Uygulamanın EXE dosyasının adını ve yolunu öğrenmek istiyorsanız ExecutablePath özelliğine bakabilirsiniz. Aynı bilgiyi Environment sınıfının CurrentDirectory özelliğinde bulmak mümkündür.
TextBox1.Text = Application.ExecutablePath
Idle Olayı
Çalıştırdığınız Visual Basic uygulaması herhangi bir işlem yapmazken Application sınıfının Idle olayı meydana gelmektedir. Otomatik olarak hazırlanan Application nesnesinin bu olayı için kod yazarsanız bazı işlemlerin periyodik olarak yapılmasını sağlayabilirsiniz. Örneğin kullanıcıyı aktif kontrol hakkında bilgilendirmek istiyorsanız aşağıdaki gibi bir metot hazırlayabilirsiniz. Hemen eklemek gerekirse formun üzerinde herhangi bir kontrol yokken bu kod hata üretir.
Private Sub OnApplicationIdle(ByVal sender As Object, ByVal e As EventArgs) Dim kontrol_adi As String kontrol_adi = Me.ActiveControl.Name Me.Text = kontrol_adi End Sub
Application sınıfının Idle olayına adı aktarılacak metodun 2 parametreye sahip olması gerekiyor. İlk parametre Object tipinde iken 2. parametre EventArgs tipindedir. 2. parametreye ad verirken Microsoft’un tercihine bağlı kaldım ve "e" adını verdim. Böylece parametre adı hırsızı olarak suçlanma ihtimaline karşı tedbir almış oldum.
Bu şekilde metot hazırladıktan sonra Application sınıfını, daha doğrusu olay yöneticisini bundan haberdar etmek için formun Load olayı ile ilgili metoda aşağıdaki gibi satır yazdım. Bu andan itibaren hangi kontrolün üzerine gidilirse o kontrolün ve kontrolün türetildiği sınıfın adı formun başlığına yazılır.
Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load AddHandler Application.Idle, AddressOf OnApplicationIdle End Sub
Klavyenin Caps Lock ve Num Lock gibi tuşlarının devrede olup olmadığı konusunda kullanıcıyı bilgilendirirken Application sınıfının Idle olayından yararlanabilirsiniz. Bu tuşları kontrol ederken Windows’un GetKeyState fonksiyonundan yararlanmak gerektiği için Imports deyimi ile System.Runtime.InteropServices’teki sınıflardan yararlanmak istediğimi işaret ettikten sonra bu fonksiyonu Class bloğu içinde aşağıdaki gibi deklare ettim.
<DllImport("user32.dll")> _ Public Shared Function GetKeyState(ByVal key As Integer) As Integer
End Function
Fonksiyonu bu şekilde deklare ettikten sonra yukarıda hazırlayıp Application_idle() adını verdiğim metotta bu fonksiyondan yararlanıp Caps Lock tuşunu aşağıdaki gibi kontrol edip kullanıcıyı bilgilendirdim.
Private Sub OnApplicationIdle(ByVal sender As Object, ByVal e As EventArgs) If (GetKeyState(&H14) = 1) Then Me.Text = "Klavye BÜYÜK Harfe Kilitli" Else Me.Text = "Form1" End If End Sub
Burada uygulaması Idle modunda iken veya herhangi bir işlem yapmıyorken Windows’un GetStateKey() fonksiyonu ile Caps Lock tuşunun basılı durumda olup olmadığını kontrol ettim. Bunu yaparken GetStateKey fonksiyonuna 16 tabanlı 14 sayısını parametre olarak verdim. GetStateKey’i aşağıdaki gibi kullanıp kodu daha okunur yapmak mümkündür.
Private Sub OnApplicationIdle(ByVal sender As Object, ByVal e As EventArgs) Dim sonuc As Integer = CType(Keys.CapsLock, Integer) If GetKeyState(sonuc) = 1 Then Me.Text = "Klavye BÜYÜK Harfe Kilitli" Else Me.Text = "Form1" End If End Sub
Number Lock tuşunun devrede olup olmadığını araştırmak istemiş olsaydım Windows’un GetStateKey fonksiyonuna 16 tabanlı 90 sayısını aşağıdaki gibi parametre olarak verirdim.
Private Sub OnApplicationIdle(ByVal sender As Object, _ ByVal e As EventArgs) If (GetKeyState(&H90) = 1) Then Me.Text = "Num Lock Tuşu devrede" Else Me.Text = "Form1" End If End Sub
DoEvents() Metodu
Bazen yapılan işlem uzun sürebilir. Uzun süren işlem tamamlanıncaya kadar VB uygulamanıza başka işlemler yaptırmak istiyorsanız Application sınıfının DoEvents() metodundan yararlanabilirsiniz. Örneğin bilgisayarın bir portunu 30 saniye boyunca dinlemek gerektiğinde port dinleme işlemi boyunca aynı program dahilinde başka işlemlere izin verilsin istiyorsanız DoEvets() metodunu kullanmalısınız. Bu konuda bilgi vermek için forma “Başlat” adında bir düğme yerleştirdim ve aşağıdaki gibi basit 2 döngü hazırladım.
Private Sub Baslat_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Baslat.Click Me.Text = "Döngüde bulunuluyor" Dim Str As String Dim takim(10) As Char For i As Integer = 0 To 90000000 Str = "Fenerbahçe" For j As Integer = 0 To 9 takim(j) = Str(j) Next Next Me.Text = "Döngünden çıkılmış" End Sub
Alışkanlıklarım gereği bu koddaki for döngüsünün kontrol değişkenine “i” adını verip yine risk almışım. Umarım i’yi değişken adı olarak namı hesabına kaydeden yerli programcılık kitabı yazarı bana kızıp buyur karakola demez. İç-içe döngüler kullandığım bu kod işletildiğinde döngüden çıkılana kadar aynı uygulama dahilinde başka bir işlem yapılamaz. Bunu göstermek için forma 2. bir düğme yerleştirdim ve bu düğmenin Click olayını temsil eden metoda bir satır yazdım. Aşağıda verdiğim ekran görüntüsünü aldığım sırada döngüden henüz çıkılmadığı için “Mesaj” düğmesi tıklansa bile tepki alınamaz.
Döngü içinde Application sınıfının DoEvents() metoduna yer verilmiş olunsaydı döngü devam ederken uygulama dahilinde başka bir işlemi yapmak mümkün olurdu. Koda DoEvents() metodu eklendiğinde döngünden çıkma süresi artar.
For i As Integer = 0 To 90000000 Application.DoEvents() Str = "Fenerbahçe" For j As Integer = 0 To 9 takim(j) = Str(j) Next Next
Bazen programın işletiminin belli noktalarda belli bir süre durdurulması istenir. Programın işlemini System.Theading’deki Theared sınıfından yararlanarak belli süreler için durdurabilirsiniz. Bu işlemin nasıl yapıldığını aşağıda görebilirsiniz.
Private Sub Form1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Click Me.Text = "Bekleme anı" System.Threading.Thread.Sleep(10000) Me.Text = "Çalışma anı" End Sub
Application Sınıfının Bazı Özellikleri
.NET uygulamaları için son derede önemli işlevi ve görevleri olan Application sınıfının uygulama hakkında bilgi edinmenizi sağlayan birkaç özelliği bulunmaktadır. Örneğin StartupPath özelliğine bakıp uygulamaya ait EXE dosyanın nerede olduğu veya uygulamanın hangi klasörden başlatıldığını öğrenebilirsiniz.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.Text = Application.StartupPath End Sub
Uygulamanın EXE dosyasının adını ve yolunu öğrenmek istiyorsanız ExecutablePath özelliğine bakabilirsiniz. Aynı bilgiyi Environment sınıfının CurrentDirectory özelliğinde bulmak mümkündür.
TextBox1.Text = Application.ExecutablePath
Uygulama için geçerli olan bölgesel ayarları ve kültürü öğrenmek istiyorsanız Application sınıfının CurrentCulture özelliğinden yararlanabilirsiniz. Bu özellik CultureInfo tipinde bir nesne içerdiği için bu özelliğin içeriğini okuyabilmek için daha önceden CultureInfo tipinde değişken tanımlamak gerekir. Application nesnesinin bu özelliğinin içeriğini nasıl öğrendiğimi aşağıda görebilirsiniz.
Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim kultur As System.Globalization.CultureInfo kultur = Application.CurrentCulture Me.Text = kultur.ToString() End Sub
Bu kodu işletince formun başlığına tr-TR yazıldı. Çünkü bu uygulamayı çalıştırdığım sırada kullandığım bilgisayarda geçerli kültür Türkçeydi. Bu kodu aşağıdaki gibi düzenlerseniz CurrentCulture özelliği bu kez “en-US” bilgisini içerir.
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim kultur As System.Globalization.CultureInfo kultur = New System.Globalization.CultureInfo("en-US") System.Threading.Thread.CurrentThread.CurrentCulture = kultur Me.Text = kultur.ToString() End Sub
Application nesnesinin CurrentCulture özelliği sayesinde yalnızca geçerli kültürün adı öğrenilmiyor. Çünkü CultureInfo nesnesi geçerli kültür hakkında çok sayıda bilgi içeriyor. Örneğin geçerli kültürün doğal adını aşağıdaki gibi öğrenebilirsiniz.
Dim kultur As System.Globalization.CultureInfo kultur = Application.CurrentCulture TextBox1.Text = kultur.Name TextBox2.Text = kultur.NativeName
ApplicationExit ve ThreadExit Olayları
Üzerinde çalıştığınız uygulama herhangi bir şekilde sonlandırıldığında ApplicationExit olayı meydana gelmektedir. Bu olay için bir metot hazırlayıp uygulamanın çalışması sona ermeden bu metoda yazdıklarınızı işletebilirsiniz. Bu olaydan nasıl yararlanıldığına örnek olması için forma RichTextBox ve SaveFileDialog nesnesi yerleştirip aşağıda verdiğim kodu yazdım.
Private Sub Uygulama_cikis(ByVal Sender As Object, ByVal e As EventArgs) Dim Cevap As System.Windows.Forms.DialogResult Cevap = MessageBox.Show("RichTextBox'ın İçeriği Kaydedilsin mi?", _ "Kaydetme", MessageBoxButtons.YesNo) If Cevap = Windows.Forms.DialogResult.Yes Then SaveFileDialog1.ShowDialog() Dim dosya As String dosya = SaveFileDialog1.FileName RichTextBox1.SaveFile(dosya, RichTextBoxStreamType.PlainText) End If End Sub
Bu kodda sizin için yeni bir şey yok. Bu kodun uygulama kapatılmadan önce işletilmesini sağlamak için bu metot ile Application sınıfının ApplicationExit olayıyla aşağıdaki gibi ilişkilendirilmesi gerekir.
Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Load AddHandler Application.ApplicationExit, AddressOf Uygulama_cikis End Sub
Diğer yandan Application sınıfının Exit() metodu ile uygulamanın çalışmasını sona erdirmek istemeniz halinde o sırada açık olan formlarla ilgili olarak önce FormClosing, ardından FormClosed olayları meydana gelir. Açık olan formlardan birisinin FormClosing olayı için bir metot hazırlayıp formun kapatılmasını, dolayısıyla Application’nın çalışmasının sona ermesini önleyebilirsiniz. Bu konuda bilgi vermek için 2 forma sahip bir Windows Forms uygulaması hazırlayıp ilk ve ikinci formun FormClosing olaylarını temsil etmek üzere aşağıdaki gibi 2 metot hazırladım.
Private Sub Form1_FormClosing(ByVal sender As Object, _ ByVal e As FormClosingEventArgs) Handles MyBase.FormClosing Dim Sonuc As DialogResult Sonuc = MessageBox.Show("İlk form kapatılsın mı?", _ "Kapatma", MessageBoxButtons.YesNo) If Sonuc = Windows.Forms.DialogResult.No Then e.Cancel = True End If End Sub
Private Sub Form2_FormClosing(ByVal sender As Object, _ ByVal e As FormClosingEventArgs) Handles MyBase.FormClosing Dim Sonuc As DialogResult Sonuc = MessageBox.Show("İkinci form kapatılsın mı?", _ "Kapatma", MessageBoxButtons.YesNo) If Sonuc = Windows.Forms.DialogResult.No Then e.Cancel = True End If End Sub
Bu şartlarda projenin ikinci formu da ekranda iken, Application sınıfının Exit() metodu ister projenin ilk ister 2. formundan işletilsin önce ilk formun(yani Form1 sınıfının) FormClosing olayını temsil eden metodu işletilir. İlk formun FormClosing olayını temsil eden metotta sorulan soruya hayır diye cevap verilirse uygulamanın çalışması sona ermez.
İlk formun FormClosing olayını temsil eden metotta sorulan soruya evet diye cevap verilmesi halinde bu kez 2. formun FormClosing olayını temsil eden metot işletilir. 2. formun FormClosing olayıyla ilgili metotta sorulan soruya evet diye cevap verilirse uygulamanın çalışması sona erer, hayır denilirse uygulama çalışmaya devam eder.
Uygulamanın çalışmasını hemen sona erdirmek istiyorsanız Exit() yerine ExitThread() metodunu kullanabilirsiniz. Bu metot uygulamaya ait ana Thread’i kapattığı için o sırada açık formların FormClosing olaylarını temsil eden metotlar işletilmeden uygulamanın çalışması anında sona etmektedir. Tabi bu arada Application sınıfının ApplicationExit olayıyla ilişkilendirilmiş bir metot varsa işletilir.
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Application.ExitThread() End Sub
ExitThread() veya Exit() metodu ile uygulamanın çalışması sona erdirdiğinizde ThreadExit olayı meydana gelmektedir. Bu olay için metot hazırlayıp uygulama kapatıldığında işletilmesini sağlayabilirsiniz. Örnek olması için ilk formun kod dosyasında aşağıdaki gibi düzenleyip “Uygulama_Thread_cikis” adında bir metot hazırladım.
Private Sub Uygulama_Thread_cikis(ByVal Sender As Object, ByVal e As EventArgs) MessageBox.Show("Uygulama kapatılıyor") End Sub
Bu şekilde “Application_Thread_cikis” adında bit metot hazırladıktan sonra bu metodu formun Load olayını temsil eden metotta Application sınıfının ThreadExit olayıyla ilişkilendirdim.
Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load AddHandler Application.ThreadExit, AddressOf Uygulama_Thread_cikis End Sub
Sizler bu metoda başka bir ad verebilirsiniz. Bu hazırlıktan sonra uygulama çalıştırılıp herhangi bir şekilde kapatıldığında bu metot işletilir. Ancak uygulamayı ExitThread() metodu ile kapatmanız halinde MessageBox sınıfının Show() metodunun kendisine parametre olarak verilen bilgiyi ekrana getirmesi ile diyalog kutusunun kapanması bir olur.
Başka bir deyişle kullanıcı MessageBox ile ekrana getirilen mesajı göremez. Bu uygulama konsol uygulaması olsaydı ekrana yazılan bilgileri sonradan okuyabilme imkanı olurdu. Bu metodu aşağıdaki gibi düzenleyerek uygulamanın kapatılması konusunda diske bir şeyler yazabilir veya bilgi kaybını önlemek bazı işlemleri yapabilirsiniz.
Private Sub Uygulama_Thread_cikis(ByVal Sender As Object, ByVal e As EventArgs) Dim yol As String = "C:\kapatma.txt" Dim akis As New FileStream(yol,FileMode.Create,FileAccess.Write) Dim yazma As New StreamWriter(akis) yazma.WriteLine("Uygulama bilinmeyen bir nedenle kapatıldı") yazma.WriteLine(DateTime.Now.ToLongTimeString()) yazma.Close() End Sub
UseWaitCursor Özelliği
Application sınıfının yukarıda saydığımız özelliklerine ek olarak UseWaitCursor adında bir özelliği var. Boolean tipte bilgi içeren bu özelliğin içeriği değiştirilebilmektedir. Başlangıçta false olan bu özellik True yapıldığında fare işareti meşgul yani kum saati şeklini alır. Bu özellikten uygulama uzun süren bir işlem yaparken kullanıcıya beklemesi gerektiği uyarısı yapma gereği duyulduğunda yararlanılabilir.
Application.UseWaitCursor = True
Açık Formlar Hakkında Bilgi Edinmek
Yukarıdaki sayfalarda Visual Basic uygulamasının açık formları hakkında bilgi edinirken Visual Studio tarafından hazırlanan MyApplication sınıfının OpenForms özelliğinden yararlanmıştık. Aynı bilgileri isterseniz Application sınıfının OpenForms özelliğinden yararlanarak edinebilirsiniz.
Bu özellik hakkında bilgi vermek için Visual Studio ile hazırladığım projeye 2. bir form dahil edip ilk forma bir ListBox ve bir düğme yerleştirdim. Proje çalıştırıldığı zaman 2. formun kendiliğinden ekrana gelmesini sağlamak için ilk formun Load olayını temsil eden metodu aşağıdaki gibi düzenledim.
Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Dim F2 As Form2 F2 = New Form2() F2.Show() End Sub
Bu metot sayesinde proje çalıştırıldığı zaman açık olan formların sayısı ikiye çıkar. Çalışma anında ilk formdaki düğme tıklandığı zaman projedeki açık formların başlıklarının ListBox’a yazılmasını sağlamak için aşağıda verdiğim kodu hazırladım.
Private Sub Listele_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Listele.Click Dim sayi As Integer sayi = Application.OpenForms.Count For i As Integer = 0 To sayi - 1 ListBox1.Items.Add(Application.OpenForms(i).Text) Next End Sub
Bu kodda önce Application sınıfının OpenForms koleksiyonun Count özelliğine bakıp eleman sayısını öğrendim. Devamında bu elemanların Text özelliklerini elde edip ListBox’a yazdım. Tahmin edeceğiniz gibi bu kod işletildiğinde ListBox’a Form1 ve Form2 yazılır.
Tekrar etmek gerekirse açık olan her form Application sınıfının OpenForms koleksiyonun bir elemanı olmaktadır. Bu nedenle bu koleksiyondan yararlanıp açık formlar ve bu formlara yerleştirilmiş nesneler üzerinde işlem yapabilirsiniz. Örneğin Form1’i temsil eden Class’ta aşağıdaki gibi kod yazıp Form2’nin başlığını değiştirmek mümkündür.
Private Sub Form1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Click Application.OpenForms(1).Text = "Fenerbahçe" End Sub
Şimdi ise Form2’deki TextBox’ın içeriğini okuyup Form1’deki TextBox’a aktaracağım. Buna göre OpenForms koleksiyonundan yararlanıp formlar üzerinde istenen işlemleri yapmak mümkündür.
Private Sub Form1_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles MyBase.Click Me.TextBox1.Text = Application.OpenForms(1).Controls("TextBox1").Text End Sub
Şimdi örnek olması için projenin o sırada açık olan 2. formunu gizleyeceğim.
Private Sub Gizle_Click(ByVal sender As System.Object, _ ByVal e As EventArgs) Handles Gizle.Click Application.OpenForms(1).Visible = False End Sub
Uygulamanın açık olan 2. formunu kapatmak istemiş olsaydım aşağıdaki gibi kod yazabilirdim. Kapatılan form Application sınıfının OpenForms koleksiyonundan otomatik olarak silinmektedir. Farklılık olsun diye önce OpenForms koleksiyonundaki Form nesnesini elde ettim ondan sonra kapattım. Tabii OpenForms koleksiyonundaki ilk formu kapatmanız halinde uygulamanın çalışmasını sona erdirmiş olursunuz.
Private Sub Kapat_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Kapat.Click Dim F2 As Form F2 = Application.OpenForms(1) F2.Close() End Sub
ApplicationContext Sınıfı
Bu kısımda konunun ayrıntılarına fazla girmeden Application sınıfı ile birlikte kullanılan ApplicationContext sınıfından söz edeceğim. Bu düşünceyle Visual Studio sayesinde aşağıdaki gibi kısıtlı özelliklere sahip bir konsol uygulamasını hazırladım.
Class ana_sinif Shared Sub Main() End Sub End Class Daha önceki konulardan bildiğiniz gibi Visual Studio tarafından konsol uygulamaları için bile çok sayıda dosya hazırlanmaktadır. Solution Explorer penceresinden yararlanarak bu dosyaların hepsini sildikten sonra aşağıdaki gibi bir kod dosyası hazırladım. Ayrıca Project Properties penceresinden yararlanıp bu uygulamanın tipini Windows Forms Application olarak ayarladım.
Main() metodu bu şekilde düzenlenen uygulama çalıştırılırsa kullanıcıya yansıyan bir şey olmaz ve bu uygulamanın çalışmasını sona erdirmek için Windows’un Görev Yöneticisi penceresinden yararlanmak zorunda kalınır. Çünkü artık "konsol uygulaması" olmayan bu uygulamanın Main() metodunda Application sınıfının Run() metoduna yer verilmesine rağmen çalışmasının nasıl sona ereceği konusunda herhangi bir hazırlık yapılmadı.
Daha önce verilen Konsol Uygulamaları adlı bölümde Run() metodunu kullanırken kendisine System.Windows.Forms’deki Form sınıfının mirasçısı bir sınıfın örneğini yani form nesnesini parametre olarak vermiştik. Bu nedenle uygulamanın kontrolü Run() metoduna parametre olarak verilen Form nesnesine geçiyordu. Söz konusu form nesnesine kaynaklık eden sınıfın olayları için kod yazarak birçok işlemi yapmak mümkündü. Örneğin Run() metoduna parametre olarak verilen Form nesnesine kaynaklık eden sınıfın FormClosing olayını temsil eden bir metot hazırlayıp formun dolayısıyla Application’nın çalışmasının sona ermesini kontrol altında tutmak mümkündür.
Run() metodunun gerçekte overload edilmiş 3 ayrı sürümü bulunmaktadır. 3. sürüm System.Windows.Forms’deki ApplicationContext tipinde bir nesneyi parametre olarak almaktadır. Önceden ApplicationContext nesnesi hazırlayıp Application sınıfının Run() metoduna parametre olarak verip Application üzerinde daha fazla kontrole sahip olmak mümkündür. Bu konuda bilgi vermek için yukarıda hazırladığım kod dosyası içinde aşağıdaki gibi ApplicationContext sınıfının mirasçısı bir sınıf hazırladım.
Public Class Context_sinifi Inherits ApplicationContext Private Form1 As Form Public Sub New() MyBase.New() Form1 = New Form() Form1.Text = "Form1" Form1.Show() End Sub End Class
Son derece kısıtlı özelliklere sahip olan bu Class’ın yapıcı metodu içinde Form tipinde bir nesne hazırlanıp bu nesne Show() metodu ile ekrana getirilmektedir. .NET Framework ile gelen ApplicationContext sınıfının mirasçısı sınıfı bu şekilde hazırladıktan sonra Main() metodunu içeren asıl sınıfı aşağıdaki gibi düzenledim.
Imports System.Windows.Forms Class ana_sinif Shared Sub Main() Dim Context As New Context_sinifi() Application.Run(Context) End Sub End Class
Bu değişiklikten sonra uygulama çalıştırılırsa Run() metoduna parametre olarak verilen ve ApplicationContext sınıfının mirasçısı “Context_Sinifi” adını verdiğim sınıfın yapıcı metodu geri planda işletilir ve ekrana yapıcı metot dahilinde hazırlanan form getirilir. Bu hali ile ApplicationContext sınıfının mirasçısı yapıp örneğini Run() metoduna parametre olarak verdiğim sınıfın herhangi bir artısı yoktur. Bu sınıfın nasıl işlevsel olabildiğine örnek olması için aşağıdaki gibi System.Windows.Forms’deki Form sınıfının mirasçısı 2 sınıf hazırladım.
Public Class Form1_sinifi Inherits System.Windows.Forms.Form Public Sub New() MyBase.New() Me.Size =New System.Drawing.Size(300, 250) Me.Text = "Form1" End Sub End Class
Public Class Form2_sinifi Inherits System.Windows.Forms.Form Public Sub New() MyBase.New() Me.Size = New System.Drawing.Size(300, 250) Me.Text = "Form2" End Sub End Class
Bu örneğin benzerini ilk olarak Microsoft kaynaklı bir sitede görmüştüm. Yani yarın bir gün yerli bir programcılık kitabı yazarı çıkıp bu örneği Memik Yanık benim kitaptan çalmış derse bilin ki kendisi de bu siteden yararlanıp sonra kendisini bu sınıfın mucidi ilan ediyor.
ApplicationContext sınıfının mirasçısı yapacağım sınıfta System.Windows.Forms.Form sınıfının mirasçısı iki sınıfın örneğini alacağım. Dolayısıyla ApplicationContext sınıfının mirasçısı sınıfın örneğini alıp Application nesnesinin Run() metoduna parametre olarak verdiğimde ekrana aynı anda 2 formu getirmiş olacağım. ApplicationContext’in mirasçısı “Context_sinifi” adını verdiğim sınıfın son halini aşağıda verdim.
Public Class Context_sinifi Inherits ApplicationContext Private Form1 As Form1_sinifi Private Form2 As Form2_sinifi Public Sub New() MyBase.New() Form1 = New Form1_sinifi() Form2 = New Form2_sinifi() Form1.Show() Form2.Show() End Sub End Class
Main() metodunu içeren sınıfta herhangi bir değişiklik yapmadan uygulama çalıştılırsa ApplicationContext sınıfının mirasçısı sınıfın yapıcı metodu işletilir ve ekrana 2 ayrı form getilir. Bu formlar birbirinden bağımsız oldukları için birisinin kapatılmasından diğeri etkilenmez. Aşağıda verdiğim ekran görüntüsünü bu uygulamayı çalıştırdıktan sonra aldım.
Bu hali ile uygulama dahilinde ekrana getirilen her iki form da kapatılsa bile uygulama çalışmaya devam edeceği için Windows’un Görev Yöneticisi penceresine başvurmak zorunda kalınılır. Bunun önüne geçmek için önce açık form sayısını tutacak bir değişken tanımlayacağım. Ardından kapatılan form projedeki açık formlardan sonuncusu ise uygulanmanın çalışmasını sona erdireceğim. Tabi açık formlardan herhangi birisi kapatıldığı zaman işletilmek üzere OnFormClosed() adında bir metot hazırladım. Örneğini Application sınıfınn Run() metoduna parametre olarak vermek üzere hazırladığım ApplicationContext sınıfının mirasçısı sınıfın son halini aşağıda verdim.
Public Class Context_sinifi Inherits ApplicationContext Private form_sayisi As Integer Private Form1 As Form1_sinifi Private Form2 As Form2_sinifi Public Sub New() MyBase.New() form_sayisi = 0 Form1 = New Form1_sinifi() form_sayisi = form_sayisi + 1 Form2 = New Form2_sinifi() form_sayisi = form_sayisi + 1 Form1.Show() Form2.Show() End Sub Private Sub OnFormClosed(ByVal sender As Object, ByVal e As EventArgs) form_sayisi = form_sayisi - 1 If (form_sayisi = 0) Then ExitThread() End If End Sub End Class
Bu şekilde düzenlenen sınıfın örneği Application nesnesinin Run() metoduna parametre olarak verildiğinde uygulama yine hatasız çalışır ve ekrana 2 form gelir ama bu formlar kapatıldığında uygulamanın çalışması geri planda devam eder. Çünkü bu hali ile OnFormClosed adını verdiğim metot çalışmaz. Açık formlardan birisi kapatıldığında bu metodun çalışabilmesi için bu metot ile söz konusu formun OnClosed olayı arasında ilişki kurulmalıdır. Bu ilişkinin AddHander anahtar kelimesi ile kurulduğunu biliyorsunuz. Projedeki formların OnClosed olayları ile OnFormClosed adını verdiğim metot ile ilişki kurulmuş halini aşağıda görebilirsiniz.
Public Class Context_sinifi Inherits ApplicationContext Private form_sayisi As Integer Private Form1 As Form1_sinifi Private Form2 As Form2_sinifi Public Sub New() MyBase.New() form_sayisi = 0 Form1 = New Form1_sinifi() form_sayisi = form_sayisi + 1 AddHandler Form1.Closed, AddressOf OnFormClosed Form2 = New Form2_sinifi() form_sayisi = form_sayisi + 1 AddHandler Form2.Closed, AddressOf OnFormClosed Form1.Show() Form2.Show() End Sub Private Sub OnFormClosed(ByVal sender As Object, ByVal e As EventArgs) form_sayisi = form_sayisi - 1 If (form_sayisi = 0) Then ExitThread() End If End Sub End Class
Her ne kadar projede son form kapatıldığında ExitThread metodu ile uygulamanın çalışmasını sona erdirdiysem bile sizler Application sınıfının Exit() metodunu kullanabilirsiniz.
Şimdi se Application sınıfının ApplicationExit olayı için kod yazacağım. Bu amaçla “Context_sinifi” adını verip ApplicationContext sınıfının mirasçısı yaptığım sınıfta aşağıdaki gibi bir metot hazırladım.
Private Sub OnApplicationExit(ByVal sender As Object, _ ByVal e As EventArgs) MessageBox.Show("Uygulama kapatılacak") End Sub
Bu şartlarda uygulama Exit() veya ExitThread() metodu ile sonlandırılsa bile bu metot işletilmez. Çünkü Application sınıfının ApplicationExit olayı ile bu metot henüz ilişkilendirilmniş değildir. OnApplicationExit adını verdğim metot ile Application nesnesinin ApplicationExit olayını ilişkilendirmek için “Context_sinifi” adını verdiğim sınıfın yapıcı metoduna aşağıda verdiğim satırı ekledim. Gördüğünüz gibi ApplicationContext sınıfını kullanmak Application sınıfı üzerinde size ek kontrol imkanları sağlamaktadır.
AddHandler Application.ApplicationExit, AddressOf OnApplicationExit
Kitaptan aldığım bölüm burada sona eriyor. Elbette Visual Basic 9.0 kitabımda yukarıda sözü edilen sınıfları bütün yönleriyle anlatamadım. Çünkü kitabın sayfa sayısı daha fazla artsın istemedim. Memik Yanık tarafından yazılan kitapların az satması için seferber olup akla ziyan iftiralar atanlar bakalım bu metni hangi kaynaktan çevirdiğimi ileri süreceklerdir? Ne de olsa çok sınırlı ingilizceyle çeviri yapabilmek dünyada bir Memik Yanık’a özel bir beceridir(!). Yani bazılarına kalırsa Memik Yanık bilmediği dilden çeviri yapabilir. |