Csharp İle Windows Programlama (2) - Window Classes - C# Webmaster bilgi bankası, knowledge base Webmaster Araçları

AnaSayfa > C# > Csharp İle Windows Programlama (2) - Window Classes
Kategori: C#
Gönderen: Admin
Tarih: 2008-11-11
Puan: 6   Puan:6 | Katılımcı:4 | Katılımcı : 4
Okunma: 4559
  
 
1 puan 2 puan 3 puan 4 puan 5 puan 6 puan 7 puan 8 puan 9 puan 10 puan

Windows, adı üzerinde bir pencereler işletim sistemidir. Sistem içerisinde açılan tüm pencereler aslında daha önceden tanımlanmış bir pencere sınıfının nesnesidir. Bir pencere açılmak istendiğinde sistem açılacak pencereye ait tanımlanmış olan sınıfı bulur ve bu sınıftan bir nesne yaratarak kullanıcıya bir nesneyi gösterir. Tabi ki hazırlanan sınıfların içerisinde birçok özelliği ve yapılan işlemlere tepki verecek delegeleri ve olayları vardır. Ayrıca her sınıf için hazırlanmış işlemleri yapacak pencere fonksiyonları (Windows Procedure – WinProc) da bulunur.

Herhangi bir program bir pencere sınıfından bir nesne yaratmak istediğinde sınıfı sistem için de kullanılabilir hale getirmek için belirtilen sınıfı sisteme kaydetmek (register) zorundadır. Bu kayıt etme işlemi, pencere sınıfı ile birlikte bu sınıfa bağlı özellikler (Properties), sınıf stili, pencere fonksiyonunu da kaydetmek zorundadır. Bu kayıt işlemi sistem içerisinde gerçekleşmezse sistem sınıfı tanımlayamadığı için belirtilen sınıftan bir nesne yaratılamayacaktır. Kayıt işlemi doğru biçimde gerçekleşirse CreateWindow() ve CreateWindowEx() fonksiyonları kullanılarak sistem içersinde pencere istenilen sayıda yaratılabilir.

İşletim sistemi içersinde pencere sınıfları üçe ayrılır; Sistem sınıfları, Program Global ve Program Lokal sınıfları. Şimdi sırasıyla bu sınıfları inceleyelim.



Sistem Sınıfları (System Classes):



Sistem sınıfları, programcıya ihtiyaç duymadan sistem içersinde varsayılan olarak zaten bulunan ve yine sistem tarafından kayıt edilen sınıflardır. Bu sınıflar birçok programcı için hazır olarak sistem içersinde bulunur. Örnek olarak buton, edit, combo kontrolleri gibi.



Not: Win95/98/Me işletim sistemlerinde sistem bu varsayılan sınıfların tamamını sistem açılışı esnasında kayıt ederek kullanıma açar. WinNT, Win2000/XP işletim sistemlerinde ise sistem bu sınıfları ilk kullanılmak istendiklerinde kayıt ederek kullanıma açar. Bu sayede sistem daha hızlı biçimde açılır.



  Programlar bu sistem sınıfları kullanmak istediklerinde sistem programlara bu sınıflardan bir kopya üretir ve programlar bu kopya sınıf üzerinde işlem yaparlar. Her programın kendisine ait diğerleri ile aynı özelliklere sahip olmasına rağmen farklı sınıf kopyaları bulunduğu için sınıflar üzerinde belli yöntemlerle yapılan değişiklikler diğerlerine etki etmez.

Buton, edit, combo, listbox gibi kontrollerin dışında sistemin kendisinin kullandığı ve normal şartlar altında programcıya sağlamadığı kontrollerde vardır. Bu kontroller aşağıda verilmeye çalışılmıştır.



Tablo 2.1







#32768



Menu sınıfı





#32769



Masaüstü (desktop) sınıfı





#32770



Diyalog kutuları (Dialog Box) sınıfı





#32772



WindowsNT/2000/ XP: İkon başlıkları sınıfı





















Program Global Sınıfları:



  Bu sınıflar programcı tarafından yazılmış, sistem tarafından sağlanmış sınıflardan başka ve genelde farklı olan bileşenlerdir. Bu bileşenler sistem içersinde birçok program tarafından kullanılabilir durumdadır. Bu nedenle global sınıflar olarak yorumlanır. Sistemin sağladığı sınıflar (bu anlmada bileşenler) yetersiz kaldığında her programcı kendisi için kendi programına özel bileşenler tasarlar ya da başka programcılar tarafından tasarlanmış bu bileşenleri kullanır -ya da satın alır. Bu kitap dâhilinde kendi bileşenlerimizi tasarlamayı ayrıca öğreneceğiz.

; Bu sınıflar genelde bir .dll dosyası içine gömülür ve farklı farklı programlarda istenilen sayıda kullanılabilir. Tanımlanan bu sınıfları kullanıma açmak için sınıf önce RegisterClassEx() fonksiyonu kullanılarak sisteme kayıt edilir. Bu aşamadan sonra hazırlanan sınıf sistem içersinde yazılan tüm programlar tarafından kullanılabilir hale gelir. RegisterClassEx() fonksiyonun kullanılması sonucunda sistem belirtilen sınıfa ait .dll dosyasını belleğe yükler. Belleğe yüklenen sınıftan bir nesne yaratılmak istendiğinde sistem bu nesne için gerekli alanı heap üzerinde açar ve sınıfı başlatır. Aynı şekilde bir sınıfın kaydedilmesinden sonra sınıfın kaydının silinmesi ve bellekte kaplamış olduğu yerin serbest bırakılması istenirse UnregisterClass() fonksiyonu kullanılabilir. Bu nesnelerin yaratılması, yok edilmesi, kullanılması ve bellek yönetimi gibi konular Komple Referans kitabımızda anlatılmıştır. Bu tip konuları bilmiyorsanız önce bu konuların öğrenilmesi daha fazla devam edebilmek için gereklidir.



Not: Önceden hazırlanmış bir sınıfın sistem başlatıldığı anda sisteme kayıt edilmesini istiyorsanız .dll dosyasının adı ve tam yolunu Registry içerisindeki AppInit_DLLs kısmına yazılmalıdır.

; HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows



Program Lokal Sınıfları:



Program lokal sınıfları aynı global sınıflarda olduğu gibi yaratılır ve yok edilirler ve genelde .dll dosyaları içerisine gömülürler. Aralarındaki tek fark program lokal sınıflarının sadece yazılan program için geçerli olmasıdır. Lokal sınıflar sadece belirtilen program için olduğundan dolayı program sonlandığında otomatik olarak kayıtları silinir ve bellekten atılırlar. Tabi istenirse yine UnregisterClass() fonksiyonu kullanılarak program kapatılmadan da yok edilebilirler.



Pencere Sınıfının Yaratılması:



  Sistem yukarıda anlatılan üç çeşit sınıfın her biri için bir yapı listesi tutar. Herhangi bir program bu sınıflardan bir nesne yaratmak için CreateWindows() ve ya CreateWindowsEx() fonksiyonunu çağırdığında sistem sırasıyla aşağıdaki işlemleri gerçekleştirir.



·   Program lokal sınıfların listesini tarayarak liste içerisinde yaratılmak istenen sınıfın bulunup bulunmadığına bakar. Bu kontrol işlemi örnek handle numarası ile modülün örnek numarasının bir birini tutması ile olur.

·   Eğer sınıf, lokal sınıf içerisinde bulunamazsa sistem, program global sınıf listesine bakarak sınıfı burada arar.

· Eğer sınıf, global sınıf içerisinde de yoksa bu kez sistem, sınıfı sistem sınıfları içerisinde arar.



Program tarafından yaratılan tüm pencereler bu sistemi kullanarak yaratılırlar. Hatta program adına sistemin yaratmış olduğu diyalog kutuları da bu sırayı takip ederler. Eğer üç aramada da istenen sınıf bulunamamışsa program istisna vererek sonlanır.

İlginç bir şekilde yaratılma işlemi CreateWindows() ya da CreateWindowsEx() fonksiyonlarıyla olduğu ve bu iki fonksiyonunda yaratılacak sınıfın adına göre hareket ettiği için bu yaratılma esnasında sistemde tanımlı bir sınıfın adı ile aynı isme sahip bir sınıf tanımladığınızda sistem, önce program lokal ve global sınıflarına baktığı için kendi içinde tanımlı olan sınıfı değil programcının tanımlamış olduğu sınıfı yaratacaktır (Overriding). Ancak bu işlem sadece kullanılan program için geçerli olacak diğer programlar yine sistemin tanımlamış olduğu sınıfı kullanacaktır.

Bütün bu bilgilerden sonra bir sınıf sistem içersinde programcı açısından bakıldığında nasıl yaratılır. Tanımlanmış olan bir sınıf, sınıfa ait tüm nitelikleri içerisinde barındır. Bu nitelikler, sınıfın stili, menüsü, ikonu vs. olarak belirlenir. Bunlara ek olarak sınıf aynı zamanda bu sınıfa ait bir Pencere Fonksiyonuda (Windows Procedure – WidProc) tanımlar. Sınıfa ait tüm nitelikler WNDCLASSEX yapısı içerisinde tanımlanmıştır. Tanımlanan sınıf yapıyı gerekli tüm bilgilerle doldurup öncelikle RegisterClassEx() fonksiyonu ile sisteme kayıt eder. Sınıfı, program global sınıf olarak kayıt etmek istiyorsanız, WNDCLASSEX yapısı içerisinde bulunan “style” alanını CS_GLOBALCLASS olarak belirlemelisiniz. (CS_ ön eki “class style” yani sınıf stili kelimelerinin baş harflerinden oluşur)

RegisterClassEx() ve RegisterClassExA() fonksiyonunu kullanarak sınıfı ANSI karakter seti ile kayıt ederseniz artır bu sınıfa parametre olarak göndereceğiniz tüm karakter katarları ANSI olarak yorumlanır. Aynı şekilde sınıfı RegisterClassEx() ve RegisterClassExW() fonksiyonları ile Unicode olarak kayıt ederseniz tüm parametreler Unicode olarak değerlendirilir. Aynı zaman da IsWindowUnicode() fonksiyonu kullanılarak sınıfın ANSI mi yoksa Unicode mu olarak kaydedildiği bulunabilir.

Sınıfı kaydeden program sınıfın sahibi olarak (owner) yorumlanır. Sistem sınıfın sahibi olan programı WNDCLASS yapısı içersindeki hInstance handle numarasına bakarak bulur. Win95/98/Me versiyonlarında sınıfı kayıt eden program sonlandığında kayıt edilen sınıfta yok edilir. WinNt/2000/XP sistemlerinde ise sistem bu sınıfları program sonlandığında otomatik yok etmez. Bu nedenle bu sınıfların sahibi program UnregisterClass() fonksiyonunu çağırarak bu sınıfları kendini kapatmadan önce yok etmelidir. Eğer bu kayıt edilme işlemini kendini kapatmadan önce kaldırmazsa ve sistem sahibi kapandığı için aslında olmayan bu sınıfı çağırmaya kalktığında bir istisna durumu oluşur (Access Violation) Bunun nedeni kullanıma açık olan pencere fonksiyonun sınıfı kayıt eden program yok edildiği için bellek üzerinde artık bulunmamasıdır.



WNDCLASSEX Yapısı:



Bu yapı içerisindeki bilgiler yaratılacak sınıfa ait temel özellikleri belirler. Bu yapı RegisterClassEx() fonksiyonuna gönderilerek sınıfa ait genel tanımlamaların tamamı sisteme kaydedilir. Aynı şekilde tüm pencere sınıfları sisteme bu şekilde kaydedildiği için bu sınıflara ait temel özellik bilgileri de GetClassInfoEx() ya da GetClassLong() fonksiyonları kullanılabilir. Aynı zamanda SetClassLong() fonksiyonu kullanılarak sisteme kaydedilmiş bir sınıfa ait temel niteliklerde değiştirilebilir.

Aslında bu yapı bir çok veri içermesine rağmen sistem sadece üç adet veriye kesin olarak ihtiyaç duyar; sınıf adı, pencere fonksiyonu adresi ve örnek handle numarası (instance handle). Bunların dışındaki veriler tamamen sınıfın kendi niteliklerini belirlemek için kullanılır ve sistem tarafından açıkça istenmezler. Gerekli olmayan noktalarda değerleri null ve ya sıfır (0) olarak belirlenebilir. Şimdi bu yapının tüm elemanlarını tek tek inceleyelim.



  Sınıfı Adı (Class Name); bu alan aslında belirtilen sınıfı tüm sınıflardan ayırmak için kullanılan kimlik bilgisini oluşturur. Bu alanın yapı içersindeki adı lpszClassName olarak belirlenmiştir. Bu alana bir karakter katarı atayarak belirtilen sınıfın adı yapı içersinde belirlenmiş olur. Belirtilen ismin tek olması sadece kullanılan proses için gereklidir. Ancak sistem içersinde farklı prosesler için aynı isme sahip sınıflar olabilir. Zaten ancak bu sayede sistem sınıflarını yukarıda anlatıldığı şekilde “override” edebilirsiniz. Ayrıca sınıf isimlerinin mümkün olduğunda kısa olması sistem içersindeki “Atom Tablosu” içersinde yer kapladıkları için gereklidir. Kayıt edilen bir sınıfın adı GetClassName() fonksiyonu ile alınabilir.



Pencere Fonksiyonu Adresi (WinProc Adres); sınıfa gönderilen tüm mesajların işlenebilmesi için gerekli olan pencere fonksiyonun giriş noktasını bu yapı sağlamak zorundadır. Bu giriş noktası fonksiyonun çalışmasını ve mesajların işlenmesini sağlar. Bu adres alanı belirtilen yapı içerisinde lpfnWndProc olarak belirlenmiştir. Pencere fonksiyonları detaylı şekilde incelenecektir.



  Örnek Handle Numarası (Instance Handle); sistem içerisinde kaydedilmiş tüm sınıfların hem kayıt edilmesi hem de kullanılabilmesi için gerekli alandır. Bu alan aslında tanımlama işlemi için kullanılır. Bu alan yapı içersinde hInstance olarak belirtilmiştir.



Sınıf Kursörü (Class Cursor); belirtilen sınıftan bir pencere yaratıldığında ve sistem tarafından pencere olarak kullanıcıya gösterildiğinde, kullanıcı fare kursörünü (işaretçisini) sınıfın görünen alanı üzerine getirdiğinde gösterilecek olan kursörü belirler. Sistem içersinde tanımlanmış bir çok kursör vardır. Normal, bekleme (wait), program başlama (application start) gibi kursörler örnek olarak verilebilir. Bu kursörler LoadCursor() fonksiyonu ile yüklenebilir. Yapı içerisinde bu alan hCursor olarak belirlenmiştir. Aslında bu alan sınıfın kaydedilmesi ve kullanılması için gerekli değildir. Program isterse bu alanı null olarak atayabilir.



Sınıf İkonu (Class Icon); her sınıf kendisi için bir adet küçük (16x16) ve bir adet büyük (24x24) ikon tanımlayabilir. Küçük ikonlar programın başlık çubuğunda ve Explorer içerisinde küçük ikon görünümde görülebilir. Büyük ikonlar ise Alt-Tab tuş kombinasyonu kullanıldığında task-switch ekranında ve Explorer üzerinde büyük ikon görünümünde görülebilir. Aslında bu alanda kullanılmadan sınıf kaydı ve kullanımı yapılabilir. Yapı içerisinde büyük ikon olanı hIcon, küçük ikon alanı da hIconSm olarak belirlenmiştir. Varsayılan küçük ve büyük ikon boyutları dışında programcı isterse GetSystemMetrics() fonksiyonunu kullanarak, büyük ikonlar için SM_CXICON ve SM_CYICON değerlerini küçük ikonlar için SM_CXSMICON ve _CYSMICON ikon değerlerini belirtebilir. Bu iki alanda sınıfın kaydı ve kullanımı için gerekli olmadığında programcı isterse bu iki alanı da null olarak belirtebilir. Bu durumda sistem program için varsayılan küçük ve büyük ikonları sınıfa atayacaktır. İlginç bir şekilde eğer büyük ikon tanımı yapıp küçük ikon değerini null olarak belirtirseniz sistem otomatik olarak küçük ikonu, büyük ikonu gerekli oranda küçülterek yaratacaktır. Ancak tam tersi bir durumda sistem küçük ikonu belirlediğiniz ikon olarak tanımlarken büyük ikonu varsayılan ikon olarak tanımlayacak ve küçük ikondan büyük bir ikon yaratmayacaktır. Sistem içersinde kaydedilen sınıfların ikonları WM_GETICON ve WM_SETICON mesajları kullanılarak alıp yeniden atanabilir.



Sınıf Arka Plan Fırçası (Class Background Brush); belirlenen sınıfın ekranda gösterimi sırasında alacak zemin rengi ve biçimini bu alan belirler. Bu alan yapı içerisinde hbrBackground olarak belirlenmiştir. Bu alanı istenilen şekilde yapmak için uygun GDI(+) fonksiyonları çağrılarak bir fırça (brush) belirlenir ve bu fırça yapı içersinde belirlenen alana atanır. Tabi istenirse yeni bir fırça yaratmak yerine sistem içersinde tanımlı renk değerleri verilebilir. Bu standart sistem renkleri GetSysColorBrush() fonksiyonu çağrılarak belirlenebilir.



Sınıf Menüsü (Class Menu); tanımlanan sınıf için açılabilir bir menü belirlenebilir. Belirlenen bu menü kullanıcı tarafından değişik işlemleri gerçekleştirmek için kullanılır. Belirtilen yapı içerisinde menü alanı lpszMenuName olarak belirlenmiştir. Belirtilen menünün kullanılabilmesi için programa ait kaynaklar içerisinde olması gerekir. Kaynaklar içersinde menü tanımı yapılmışsa bu menü adı ile belirtilen yapı içersindeki alana aktarılır. Eğer sınıf için bir menü tanımı yapılmamışsa ve belirtilen alan null olarak belirlenmişse sınıf için bir menü açılmaz. MDI programlarında alt form (child form) olarak bir pencere açılırsa ve açılan pencereye ait bir menü sınıfı tanımlanmış olsa bile sistem tarafından alt formlara menü kullanımı sağlanmadığı için menü yok sayılır ve görüntülenmez.

;

Sınıf Stilleri (Class Styles); belirtilen sınıf için ekstra özellikleri sağlayan alandır. Yapı içersinde style alanına gerekli veri aktarılarak sınıfın stili belirlenebilir. Bu özelliğin kullanılabilmesi için önceden tanımlanmış sabitler sistem içersinde bulunur. Bu sabitlerden biri veya birden fazlası sınıf için belirlenebilir. Bu birden fazla stili kombine şekilde kullanmak için OR (|) işareti kullanılarak stiller ayrı ayrı belirtilebilir. Örnek olarak CS_DROPSHADOW, CS_NOCLOSE ve CS_PARENTDC verilebilir. Bu noktada “device contex” denilen, gösterilen sınıfın boyanması ile ilgili tüm değerleri taşıyan bir yapı ortaya çıkıyor. Sistem, bu yapıya formun boyanması ve gösterilmesi ile ilgili tüm işlemler için ihtiyaç duyar. Konu ile ilgili daha fazla bilgi için MSDN Library’e başvurulabilir.



Ekstra Sınıf Belleği (Extra Class Memory):



Kimi durumlarda herhangi bir sınıf kaydeden program, sisteme, kaydetmiş olduğu sınıf için ekstra bellek ayırmasını söyleyebilir. Bu ekstra bellek WNDCLASS yapısının sonuna eklenir ve sistem bu noktaya bir işaretçi koyar. Açılan bu ekstra bellek sistemin kendi heap alanında açılır. Ancak ayrılan ekstra bellek maksimum 40 byte olabilir. Eğer bir program kaydetmiş olduğu sınıf için daha fazla ekstra belleğe ihtiyaç duyuyorsa bu alanı kendi prosesi içerisinde açar. SetClassLong() fonksiyonu ekstra belleğe istenilen değeri yerleştirir. Bu değer GetClassLong() fonksiyonu ile alınabilir. Ekstra bellek için ayrılacak alan WNDCLASS yapısı içersinde bulunan cbClsExtra alanına verilen değer ile belirtilir. Program kayıt etmiş olduğu sınıf için ekstra belleğe ihtiyaç duymuyorsa bu alanı sıfır (0) olarak belirtir.



Ekstra Pencere Belleği (Extra Windows Memory):



  Aynı ekstra sınıf belleğinde olduğu gibi program, kayıt edilmiş sınıftan yaratılan tüm pencereler için yine ekstra belleğe ihtiyaç duyabilir. Açılan bu ekstra bellekte yine sistemin lokal heap alanında açılır. Aynı şekilde açılan bellek alanı en fazla 40 byte olabilir. Bu nedenle pencereler için dcaha fazla belleğe ihtiyaç duyan programlar kendi proseslerini kullanmak zorundadırlar. SetWindowLong() fonksiyonu açılan bu ekstra belleğe yüklenecek değeri belirtir. GetWindowLong() fonksiyonu da bu alana yüklenen veriyi geri döndürür. WNDCLASS yapısı içerisinde cbWndExtra alanına verilen değer açılacak bellek alanının boyutunu belirler. Eğer program ekstra belleğe ihtiyaç duymuyorsa bu alanı sıfır (0) olarak belirtir.





Yorumlar
Henüz Kimse Yorum Yapmamış, ilk yorumu siz ekleyin!
Yorum Ekleme Aparatı
Yorum Eklemek için lütfen sol menuden giris yapınız..
Toplam 0 yorum listelendi.