AION - Tıkla oyna


Kullanıcı Adı:
şifre:
şifreyi Anımsa
şifrenizi mi unuttunuz?     ÜYE OL

 Tüm Forumlar
 Genel Konular
 Yazılım & Program
 Windows nedir

Not: Bir yanıt gönderebilmek için kayıtlı olmalısınız.
Kayıt olmak için, burayı tıklayın!

Ekran boyutu:
Kullanıcı Adı:
şifre:
Biçem Modu:
Biçem: KoyuıtalikAltı ÇiziliÜstü Çizili Sola YaslaOrtalaSağa Yasla Yatay Çızgi Bağlantı EkleE-Posta EkleResim Ekle Kod EkleAlıntı EkleListe Ekle
   
Mesaj:

HTML KAPALI
Forum Kodu AÇIK
Smiley'ler (Yüz ifadeleri)
Gülümseme [:)] Büyük Gülümseme [:D] Karizmatik [8D] Utanmış [:I]
Dil [:P] Kötü [):] Göz Kırpma [;)] Palyaço [:o)]
Korsan [B)] 8 Nolu Top [8] Üzüntülü [:(] Utangaç [8)]
şaşırmış [:0] Kızgın [:(!] Ölmüş [xx(] Uykulu [|)]
Öpücük [:X] Onaylayan [^] Onaylamayan [V] Soru [?]

  İmzanızın eklenmesi için seçiniz.
Bu konuya abone ol.
    

K O N U      ı N C E L E M E
STING İletim - 06/01/2006 : 18:10:09
Bu işi profesyonelce yapalım dimi? Meslek hayatımda edindiğim tüm deneyim ve bilgiyi arşivledim. Çok fazla değil ama bildiklerimi paylaşayım dedim. Umarım işinize yarar ve hoşunuza gider.
1. Windows grafik tabanlı bir işletim sistemidir.

Windows grafik mode'da çalışan bir sistemdir. Oysa DOS ve UNIX temelde text mode'da çalışır. Ancak bu işletim sistemlerinin de kullanımını kolaylaştırmak için grafik arabirimleri vardır. Ancak yalnızca Windows'da grafik mode'da program yazmak zorunlu değildir. Bir Windows programı Windows'un grafik özelliğini kullanabilir. Bu tür programlara GUI(graphical user interface) programlar denir. Zaten Windows programı denilince bu tür programlar anlaşılır. Bazı Windows programları text mod'da çalışabilir. Böyle programlara console programları denir. Console programları için özel bir bilgiye gereksinim yoktur. Programlar DOS ve UNIX'te olduğu gibi organize edilir.

2. Windows aygıt bağımsız grafik özelliğine sahiptir.

Windows'da oluşturulan grafiksel görüntüler ekran kartına, ekran moduna ve monitör tipine bağlı değildir. Yeni bir grafik kartı takıldığında önceki kart için yazılmış program aynı biçimde çalışır. Yani bu değişimlerden programlama sistemi etkilenmez.

3. Windows çok işlemli bir işletim sistemidir.

Windows aynı anda birden fazla programın bir arada çalıştırılabildiği çok işlemli(multi processing) bir işletim sistemidir. Çok işlemli çalışma zaman paylaşımlı bir biçimde yapılır. Yani her program bir süre çalıştırılarak bırakılır. Programların çalıştırılıp bırakılma işlemleri belli bir algoritma ile yürütülür. Bu algoritmaya çizelgeleme algoritması denir. Windows sistemleri döngüsel çizelgeleme(round robind scheduling) sistemi kullanır. Programların çalıştırılıp bırakılma süresine quanta denir. Windows sistemleri 20 ms'lik quanta sistemi kullanır. Bir programın bırakılarak diğer bir programın çalıştırılması işlemine görevler arası geçiş(task switch) denir. Ancak programlar çoğu zaman dışsal bir takım olayları beklerler(klavyeden bir tuşun basılmasını, porttan bir bilgi gelmesini, dosyadan veri okunması vs..). O zaman işletim sistemi ilgili programı çizelge dışı bırakır. Bu işleme programın bloke edilmesi denir. Bu dışsal olaylar gerçekleştiğinde işletim sistemi programı tekrar çizelgeye yeniden dahil eder. Ancak Windows işletim sisteminde olduğu gibi bazı sistemler öncelikli döngüsel çizelgeleme kullanabilirler. Her programın 0-31 arasında bir öncelik derecesi vardır. Sistem en yüksek öncelikteki programlar arasında çizelgeleme yapar. Ancak onlar bittikten sonra diğerleriyle uğraşılır.


Düşük öncelikli programlar yine de çalışır. Çünkü yüksek öncelikli programların hepsinin bloke olma olasılığı vardır. Tabii isterse programcı yazılım yoluyla da bloke olabilir. Windows'da bir programın minimize edilmesi bloke edilmesi anlamına gelmez.

4. Windows "preemtive" bir işletim sistemidir.

Preemtive sistemlerde işletim sistemi görevler arası geçiş işlemiyle bir programı çalıştırır, quanta süresi bittiğinde kontrolü tekrar ele geçirerek başka bir programı çalıştırır. Oysa preemtive olmayan sistemlerde bir program çalıştırıldığında görevler arası geçişin oluşması için programcının kontrolü işletim sistemine geri vermesi gerekir. Eğer vermezse tüm sistem olumsuz yönde etkilenir ve hatta kilitlenebilir. Windows 3.x sistemleri preemtive değildir. Ancak Windows 95/98/NT sistemleri preemtive'dir.

5. Windows alt işlemli çalışmanın mümkün olduğu bir sistemdir.

Alt işlem(thread) bir programın bağımsız olarak çizelgelemeye giren bir parçasına denir. C'de herhangi bir fonksiyon alt işlem olarak tanımlanabilir.Ancak bu fonksiyonun alt işlem olarak sisteme tanıtılması gerekir. Her program en azından bir alt işlem içerir, bu da programın kendisidir. Alt işlemler programın çalışma zamanı sırasında oluşturulur. Yani C programı main'den çalışmaya başladığında tek alt işleme sahiptir. Sonra programın akışı CreateThread fonksiyonuna gelir ve bir fonksiyon yeni bir alt işlem olarak devreye girer. Aslında bütün çizelgeleme alt işlem düzeyinde yapılır. Örneğin 3 proses söz konusu olsun, p1, p2, p3 adlı üç program çalışıyor olsun.



Çok işlemli çalışma pek çok algoritmanın gerçekleştirilmesini kolaylaştırmaktadır. Birden fala cpu'nun bulunduğu makinalarda hız ciddi biçimde artar. Aynı programın alt işlemleri arasındaki task switch zamanı farklı programların alt işlemleri arasındaki task switch zamanından daha azdır.

Çok işlemliliğin avantajları:
- Çok alt işlemden oluşan programlarda dışsal bir olay gerçekleştiğinde programın tamamı bloke olmaz, yalnızca bir alt işlem bloke olur. Bir döngü içerisinde bir olayın gerçekleşmesi ile ilgili işlemler yapan kodlar daha kolay tasarlanırlar.

6. Windows Intel sistemlerinde 4 Gb bellek kullanabilir.

DOS işletim sistemi ancak 1 Mb belleği kontrol edebilir. Üstelik bu 1 MB belleğin yalnızca 640 Kb'lik bölümünü programlar için kullanabilir. Oysa programlar ayrıntılı özelliklere sahip oldukça bellek gereksinimi de artar. Bir Windows exe programı istenildiği kadar uzun olabilir.

7. Windows sanal bellek kullanan bir işletim sistemidir.

Sanal belek(virtual memory) programın belli bir kısmının RAM'e yüklenerek disk ile yer değiştirmeli olarak çalıştırılması için kullanılır. Programın belirli bir bölümü RAM'e yüklenerek çalışmaya başlar, program kod ya da data bakımından RAM'de olmayan kısma erişmek istediğinde işletim sistemi programın RAM'deki bir bölümünü disk'e diskteki bölümünü RAM'e çekerek kesiksiz çalışmayı sağlar. Bütün sanal bellek kontrolü; örneğin programın neresinin diskte tutulup tutulmayacağı gibi işlemler işletim sisteminin kontrolü altındadır. Programcının sanal bellek kullanımı üzerindeki kontrolü son derece azdır. Bütün bu işlemler işletim sistemi tarafından otomatik olarak gerçekleştirilir.
Sanal bellek kullanımı hem mikro işlemcinin hem de işletim sisteminin ortaklaşa sağladığı bir işlemdir. Intel işlemcileri 80286 ile birlikte segment tabanlı sanal bellek, 80386 ile birlikte sayfa tabanlı sanal bellek kullanımına uygun tasarlanmıştır. Yani Windows altında toplam bellek RAM + boş disk alanı kadardır. Programın disk ile RAM arasında taşınmasına yer değiştirme(swap) denir. Program uzun RAM azsa fazla sayıda yer değiştirme olur, program da yavaş çalışır. Fiyat/Performans bakımından optimum RAM Windows 3.1 için 16Mb, 32 bit Windows sistemleri için 64 Mb civarındadır. Dinamik bellek fonksiyonlarıyla heap üzerinde yapılan tahsisatlar da sanal bellek kullanılarak gerçekleştirilir. Örneğin Excel büyük bir tabloyu yükleyebilmek için malloc fonksiyonu ile 200 Mb bellek isteyebilir, sistem bunu RAM'de bulamazsa disk üzerinde yer değiştirme dosyası üzerinde tahsis eder. Bu alan kullanılmak istendiğinde işletim sistemi otomatik olarak yer değiştirme yapar.

8. Win32 sistemlerinde her program sanki belleği tek başına kullanıyormuş gibi çalışır.

Win32'de görevler arası geçiş sırasında bir program bellekten tamamen atılır, diğeri belleğe tamamen yüklenir. Yani bir program çalışırken diğer programlar bellekte değildir ve onlara erişilemez. Tipik bir Windows'daki bellek yönetimi düşük seviyeli 2Gb'lık sana bellek programlar için, yüksek anlamlı 2GB'lık sanal bellek ise işletim sistemi içindir.



Çalışma sırası programa geldiğinde sanal bellek desteğiyle program 2Gb'lık alana yüklenir. Win32'de bütün göstericiler 4 byte uzunluğundadır ve bütün belleği görebilir. Örneğin iki farklı programda malloc fonksiyonu aynı adresi vermiş olabilir, ancak bu iki program tamamen izole çalıştığına göre iki adresin birbirleriyle hiç ilişkisi yoktur. Yani Windows'da bir adres söz konusu olduğu zaman o adresin hangi programa ilişkin olduğunu da bilmek gerekir. Yüksek anlamlı 2 Gb'lık alan görevler arası geçişten etkilenmez.

9. Windows dosya formatları.

İlk obj formatı 1978'deki Intel OMF(dos) formatıdır. Win32 sistemleriyle beraber COFF formatına geçilmiştir.
İlk exe formatı DOS'ta MZ(Mark Zibikowski) formatı olarak, Windos 3.x ile beraber NE(new executable) formatı kullanılmaya başlanmıştır. Win32 sistemleriyle beraber PE(portable executable) formatı kullanılmaya başlanmıştır. PE formatı mikro işlemciden ve işletim sisteminden bağımsız bir format olma iddiasındadır.

10. Kaynak kullanımı.

Bir Windows programındaki bitmap, dialog penceresi, menu, icon, string gibi görsel elemanlara kaynak(resource) denir. Kaynaklar ya doğrudan kaynak dili kullanılarak yazılırlar ya da görsel olarak kaynak editörlerinde oluşturulurlar. Tabii kaynak editörü bu görsel belirlemelerden kaynak kodunu oluşturur. Kaynak dilinde yazılmış kaynak programının uzantısı rc'dir. Bu program ismine kaynak derleyicisi denilen özel bir derleyicide derlenir ve kaynak verisi res uzantılı bir dosya halinde oluşturlur. Bu res dosyası linker tarafından PE formatının kaynak bölümü denilen bir bölümüne yerleştirilir(resource binding). Rc dosyası derlenirken gerekli bütün grafik dosyalar bulundurulmalıdır. Ancak derlendikten sonra bu dosyaların içerisindeki veriler res dosyasına aktarılır, yani rs dosyası bütün grafik bilgilerini içerir. Bu res dosyası PE formatına yazıldıktan sonra grafik dosyalarına, rc dosyasına, res dosyasına programın çalışması için gereksinim kalmaz. PE formartının kaynak bölümü tamamen dokümante edilmiştir. Bu kaynak bölümünde değişiklik yapılmasına izin veren kaynak editörleri vardır. Kaynak kullanımından amaç bir programda hiç onu derleyip link etmeden görsel değişiklikleri kaynak editörü kullanarak yapabilmektir(res dosyası üzerinde doğrudan değişiklik yapılması uygun değildir. Bu kaynak kısmı PE formatından çıkartyılabilir ve yeni bir kaynak kodu oraya yerleştirilebilir.).

11. Windows sisteminde dinamik kütüphaneler yoğun olarak kullanılır.

Kütüphane dosyaları lib ve dll uzantılı olmak üzere ikiye ayrılır. Lib dosyası içerisinden bir fonksiyon çağırılmış olduğunda linker fonksiyonların kodlarını alarak exe dosyasının içerisine yazar. Yani dosyayı çalıştırmak için lib dosyasına ihtiyaç olmaz. Oysa dll içerisindeki bir fonksiyon çağırıldığında linker yalnızca fonksiyonun hangi dll içerisinde olduğunu PE formatının import bölümüne yazar. Program çalıştırılacağı zaman Windows, PE formatının import bölümünü okur, bu programın hangi dll dosyalarını kullandığını tespit eder, programla birlikte bu dll dosyaslarını da yükler. Bu durumda dinamik kütüphane kullanan bir program ancak bu dinamik kütüphanelerle birlikte taşınarak çalıştırılabilir. Dll dosyaları tamamen PE formatındadır. Yani bir exe dosya da bir dll'miş gibi kullanılabilir.

12. Windows sistemleri UNICODE tablosunu desteklemektedir.

Bir yazı ASCII tablosunda her karakteri 1 byte olacak biçimde temsil edilir. Bu durumda 256 değişik karakter bulunabilir. Oysa UNICODE tablosunda her karakter 2 byte ile belirtilir. Dünyada kullanılan bütün semboller bu tabloya yerleştirlimiştir. Bir yazının başlangıç adresini parametre olarak alan Windows API fonsiyonlarından 2 tane vardır. Bir tanesi yazıyı ASCII tablosuna bakarak yorumler, diğeri UNICODE tablosuna bakarak yorumlar. Eğer UNICODE sistemi kullanılırsa programdaki yazılar dilden bağımsız hale getirilir.

Macar Notasyonu

Macar notasyonu Microsoft çalışanlarından Charles Simoney tarafından geliştirilmiştir. Macar notasyonu değişkenlere isim verme ile ilgili belirlemelerden oluşur. Amaç bir değişkene bakıldığında onun türünün ve hangi amaçla kullanıldığının tespit edilmesidir.

Özellikleri:

- Değişken isimleri değişkenin türünü anlatan küçük harf ön eklerle başlar, daha sonra her sözcüğün ilk harfi büyük harfle başlar.

Önek Anlamı
l long
w WORD (işaretsiz iki byte)
dw DWORD (işaretsiz dört byte)
d double
c char
p gösterici
pl long gösterici
pv void gösterici
psz sonu NULL ile biten yazıya ilişkin char göstericisi
f flag(aynı zamanda float)
b bool
lp uzak gösterici
u unsigned int


int türü çok fazla kullanıldığı için ön ek almaz. Ancak küçük harfle başlatılır, sonraki sözcüğün ilk harfi büyük harfle başlatılır(totalCost gibi).

- Macar notasyonunda alt tire kullanılmaz. Fonksiyon isimlerinin her sözcüğünün ilk harfi büyük yazılır(CreateWindow gibi). Fonksiyon isimleri önce eylemle başlar nesneyle devam eder.

- Değişken isimleri uzun olma eğilimindedir.

Macar notasyonu Windows işletim sisteminin programlamaya ilişkin dokümantasyonlarında Microsoft tarafından yoğun bir biçimde kullanılmaktadır. Windows programlamada Macar notasyonunun kullanılması gelenek haline gelmiştir.

- Yapı türünden değişkenlere ön ek getirilmez. İlk sözcük küçük harf sonraki bütün sözcüklerin ilk harfleri büyük harfle yazılır.

Windows.h Dosyası

Windows programlamasında windows.h isimli başlık dosyası ön işlemci ve derleyici için include edilmelidir. Bu dosyanın içerisinde API fonksiyonlarının prototipleri, sembolik sabitler, typedef isimleri, yapı bildirimleri vs gibi bildirimler vardır. Bu dosya ön işlemci tarafından açıldığında çok büyük bir kod derleme işlemine sokulur.

API(Application Programming Interface) Fonksiyonları

Bir işletim sisteminin çalışırken kendisinin kullandığı, programcının da dışarıdan çağırabileceği fonksiyonları vardır. Bunlara sistem fonksiyonları denir. Sistem fonksiyonlarına unix'te System Call, Windows'da ise API denilmektedir. Sistem fonksiyonları işletim sistemiyle birlikte belleğe yüklenirler. API fonksiyonları bütün programlama dillerinde ve geliştirme ortamlarında işlemleri yapabilmek için derleyici sistemleri tarafından çağırılır. Örneğin Visual Basic'te programcı API kavramını bilmese de aslında derleyici sistemi bütün işlemlerini sistem fonksiyonlarını çağırarak gerçekleştirir. Windows API fonksiyonları dll dosyaları içerisindedir ve sistemle beraber otomatik olarak yüklenirler. API fonksiyonları üç gruba ayrılır:

1. Kernel API'ler: Kernel32.dll içerisindedir. Sistemin aşağı seviyeli çalışmalarıyla ilgili sistem fonksiyonları bulunur.
2. User API'ler: User32.dll içerisindedir. Programcının doğrudan üzerinde çalıştığı konularla ilgili olan sistem fonksiyonlarıdır. Örneğin pencere işlemleri için gereken API'ler, kontrollere ilişkin API'ler vs.
3. Graphics API'ler: Gdi32.dll içerisindedir. Bütün grafik çizimlerine ilişkin sistem fonksiyonlarını içerir.

Bir Windows Programının Derlenerek Çalıştırılması

Bir Windows programının exe uzantılı hale getirilebilmesi için birkaç aşama gereklidir. Önce uzantısı c olan dosyalar derleyici tarafından derlenerek obj dosyalar dönüştürülür, sonra uzantısı rc olan kaynak dosyaları kaynak derleyicisi tarafından derlenerek res uzantılı hale getirilir, en sonunda linker tarafından obj ve res dosyaları link edilerek exe uzantılı dosya elde edilir.

c dosyaları rc dosyaları
Derleyici Kaynak derleyicisi
obj dosyaları res dosyaları
linker
exe (PE format)


Aslında linker programı exe dosyasının içerisine res dosyasını yeleştirebilecek biçimde yazılmıştır. Yani işlemler şöyle de yürütülebilir: Önce yalnızca obj'larla exe elde edilir, daha sonra res dosyası tekrar linker kullanılarak exe içerisine yerleştirilir(resource binding). Burada açıklanan işlemler komut satırından manual olarak yapılabilir. Ancak derleyici sistemleri proje dosyası kullanımıyla bu işlemleri kolaylaştırmaktadır. Bu çalışma biçimine göre önce bir proje dosyası açılır, sonra bu dosya içerisine c ve rc dosyaları yerleştirilir. Program çalıştırılacağı zaman derleyici sistemi önce c dosyalarını c derleyicisiyle, rc dosyalarını ise kaynak derleyicisi ile derler ve hep birlikte link eder.

Windows.h İçerisindeki typedef İsimleri

Windows programlamasında taşınabilirlik sağlamak amacıyla tür belirten anahtar sözcükler yerine typedef isimleri yoğun olarak kullanılır. Bu tür tanımlamalarının başlıcaları şunlardır:

typedef unsigned char BYTE
typedef unsigned short int WORD
typedef unsigned long int DWORD
typedef int BOOL /*Örneğin BOOL bir fonksiyonun başarılı ya da başarısız olduğu bilgisi için kullanılabilir. BOOL demek aslında int demektir ancak okunabilirliği arttırır. Aynı zamanda BOOL türüne eşlik eden iki makro vardır. TRUE ve FALSE. #define FALSE 0 #define TRUE 1*/
typedef unsigned int UINT /*Aslında Win32'de UINT ile DWORD arasında işlevsel bir fark yoktur. Çünkü int türüyle long türü aynı uzunluktadır.*/
typedef int INT
typedef float FLOAT

/*
DOS ve Win3.1 sistemlerinde yakın ve uzak gösterici kavramları vardır. Dolayısıyla near ve far anahtar sözcükleri geçerli bir biçimde kullanılır. Oysa 32 bit Windows sistemlerinde yakın ve uzak gösterici diye kavramlar yoktur. Bütün göstericiler 4 byte uzunluğundadır. Win32'de near ve far anahtar sözcükleri tanımlı değildir, kullanılması error oluşturur. Ancak Win3.1 sistemleriyle uyumu korumak için near ve far anahtar sözcükleri windows.h içerisindeki
#define far
#define near
satırlarıyla silinirler. Yani biz near ya da far anahtar sözcüklerini kullansak bile windows.h dosyası include edildiği için bu sözcükler koddan çıkartılır. Böylece error oluşmaz. Bu iki satır Win3.1 programlarının Win32'de hiç değişiklik yapılmadan kullanılabilmesini sağlamak için konulmuştur. Göstericilere ilişkin typedef tanımlamaları Win3.1'de oluşturulmuştur. Dolayısıyla yakın ve uzak gösterililer için farklı isimler uydurulmuştur.
*/
typedef char far *LPSTR;
typedef char *PSTR; /*far anahtar sözcüğü silindiği için LPSTR ile PSTR aynı türdür, karakter türünden gösterici anlamına gelir. Ancak hala Win3.1'den alışkanlıkla LP ön ekli typedef isimleri daha fazla kullanılmaktadır.*/
typedef unsigned short int *PWORD, *LPWORD;
typedef int * PBOOL;
typedef unsigned int *LPUINT, *PUINT;
typedef const char *LPCSTR, *PCSTR;
typedef unsigned int WPARAM;
typedef long int LPARAM; /*Win3.1'de WPARAM 2 byte LPARAM ise 4 byte uzunluğunda işaretsiz tam sayı biçimindeydi. Win32'de aralarında fark yoktur.*/
#define CONST const /*CONST yerine const yerleştirilir.*/
typedef void *PVOID, *LPVOID;

Handle Türleri

İsmine handle denilen ve ilk harfi 'H' ile başlayan bütün tür isimleri gerçekte void türünden gösterici anlamındadır.
HWND
WICON
HCURSOR
Macar notasyonunda bu türde değişken tanımlanırken değişken isminin önüne 'h' getirilir. Örneğin: HWND hwnd; /*veya void *hwnd;*/

Bir Windows Programının Organizasyonu

Bir Windows programı DOS ve UNIX'te olduğu gibi main fonksiyonundan değil, WinMain fonksiyonundan çalışmaya başlar. WinMain fonksiyonunun parametreleri main fonksiyonundan farklıdır ve işletim sistemi tarafından geçirilir. WinMain fonksiyonunun geri dönüş değeri int olmak zorundadır.
Fonksiyonun geri dönüş değerinin soluna yazılan anahtar sözcüğe fonksiyonun çağırma biçimi(calling convention) denir. Bu çağırma biçimleri pascal, cdecl veya stdcall olabilir. Microsoft firması bu anahtar sözcükleri _pascal, _cdecl, _stdcall olarak tanımlamıştır. Ancak daha sonra ANSI uyuşumu sağlamak için çift alt tireli şekillerini standartlaştırmıştır. Bugün bütün derleyiciler üç biçimi de desteklemektedir. Bu anahtar sözcüklerden hiçbiri yazılmazsa C'deki fonksiyonlar için __cdecl yazılmış kabul edilir. C++'taki sınıfa ilişkin üye fonksiyonlar için varsayılan durum __stdcall biçimindedir. Windows.h içerisinde #define WINAPI __stdcall tanımlaması vardır. WinMain fonksiyonunun çağırılma biçimi __stdcall olmak zorundadır. WINAPI zaten bu demektir(Eğer burada WINAPI ya da __stdcall yazmazsak default olarak __cdecl anlaşılır, bu da programın hatalı çalışmasına yol açar).

WinMain Fonksiyonunun Parametreleri

Bu parametreler işletim sistemi tarafından geçirilir.

- HINSTANCE hInstance
Buraya geçirilen değer exe dosyanın çalıştırılma sırasında belleğe yüklenme adresidir. Programın yüklenme adresi aslında PE formatının içerisine yazılmaktadır. Yükleme adresi derleyici seçeneklerinden çeşitli biçimlerde değiştirilebilir. Ancak değiştirilmesi için ciddi bir neden yoktur. Win9x sistemlerinde bu yükleme adresi default olarak 0x400000(4 Mb), WinNT sistemlerinde 0x100000(1Mb) biçimindedir. Yani farklı programların hInstance değerleri farklı olabilir.
16 bit Windows'da hInstance değeri programın yüklenme adresi değil programın module database adresidir. Yani 16 bit Windows'da her programın hInstance değeri birbirinden farklıdır. hInstance değeri pekçok API fonksiyonuna parametre olarak geçirilmektedir. Örneğin kaynak(resource) üzerinde işlem yapan bir API fonksiyonu bu değeri parametre olarak ister, aslında fonksiyon bu değerden faydalanarak PE formatının yüklenme adresini alır. PE formatı içerisinde kaynak bölümünün nerede başladığı bilgisi vardır. Fonksiyon kaynak bilgilerine bu biçimde erişir. hInstance değeri WinMain içerisinde global bir değişkene atanırsa her fonksiyon içerisinden kullanılabilir.

- HINSTANCE hPrevInstance
Bu değer 32 bit Windows sistemlerinde her zaman NULL olarak geçirilir. 16 bit Windows'da hPrevInstance programın kopyası birden fazla çalıştırılıyorsa önceki kopyasının hInstance değeri olarak geçirilir. Tabii program ilk kez çalıştırıldığında hPrevInstance 0 olacaktır. 16 bit Windows'da bir programın birden fazla çalıştırılması istenmiyorsa aşağıdaki gibi bir işlem yapılabilir.

if (hPrevInstance)
return 0;

Bazı işlemlerin yalnızca programın ilk çalıştırılmasında yapılması isteniyorsa:

if (!hPrevInstance) {
...........
........
........
........
}

32 bit Windows sistemlerinde hPrevINstance her zaman NULL olduğuna göre programın ilk kez çalıştırılıp çalıştırılmadığı bu yöntemle anlaşılamaz(Bu işlem için mutex nesneleri kullanılmalıdır).

- LPSTR lpszCmdParam
Komut satırı argümanlarını gösteren yazının başlangıç adresini belirtir. Komut satırı argümanları tek yazı olarak tutulur.

- int nCmdShow
Programın ana penceresinin program çalıştırıldığında hangi büyüklükte ilk kez görüntüleneceğini belirtir. Bu parametre 3 seçenek alabilir. Bunlar:

SW_MAXIMIZE
SW_MINIMIZE
SW_RESTORE

Bir Windows programı hiçbir pencere olmadan da çalışabilir. Ancak tabi istenen bu değildir.

Programın Ana Penceresinin Yaratılması

Programa ilişkin bütün pencerelerin yaratılması CreateWindow API fonksiyonu ile yapılmaktadır. Bu fonksiyonun birinci parametresi WNDCLASS türünden bir yapı değişkeninin adresini alır. Bu durumda önce WNDCLASS türünden bir yapı değişkeni tanımlanıp içinin doldurulması gerekir. CreateWindow bu yapının içerisindeki bilgileri kullanmaktadır.

WNDCLASS Yapısı

WNDCLASS yapısı bir pencerenin temel özelliklerini barındıran bir yapıdır.

WNDCLASS Yapsının Elemanları

- UINT style
Pencerenin genel türüyle ilgili bilgileri içerir. Bu eleman aslında her biti bir özellik olarak ele alınacak biçimde düşünülmüştür. Bu elemana genellikle CS_HREDRAW | CS_VREDAW değeri girilir(Windows.h içerisinde birçok sembolik sabit vardır. Bu sembolik sabitlerin hangi amaçla kullanıldığının kolay anlaşılabilmesi için isimlendirilmeleri de okunabilir bir biçimde yapılmıştır. Bir sembolik sabitin isimlendirilmesi genel olarak XX_ISIM biçimindedir. Burada XX sembolik sabitin hangi konuyla ilgili olduğunu anlatan bir ön ektir).

- WNDPROC lpfnWndProc
Pencere fonksiyonunun başlangıç adresini tutan göstericidir.

- int ***
int cbWndExtra
Pencere biçimine ilişkin yapı için ayrılacak ekstra alanların byte cinsinden değeridir. Ekstra alana nadiren gereksinim duyulur, genelde değeri sıfırdır.

- HANDLE hInstance
Bu elemana WinMain fonksiyonuna geçirilen hInstance değeri geçirilmelidir.


- HICON hIcon
Program minimize edildiğinde gösterilecek icon görüntüsünü belirlemek için kullanılır. Genellikle bu elemana Windows'un önceden tanımlanmış standart icon'larından biri yerleştirilir. İskelet programda bu elemana LoadIcon API fonksiyonu çağırılarak değer atanmıştır.
LoadIcon(NULL, IDI_QUESTION);

- HCURSOR hCursor
Windows programlamasında cursor mouse'un hareket ettirildiğindeki gösterici şekili olarak kullanılır. Mouse oku bir pencerenin sınırları içerisinde gezdirildiğinde istenilen bir şekle dönüştürülebilir. Bu eleman bu şeklin belirlenmesinde kullanılır. İskelet Windows programında bu elemana LoadCursor API fonksiyonunun geri dönüş değeri atanmıştır.
LoadCursor(NULL, IDC_ARROW);
Burada belirlenen mouse şekli ok biçimindedir.

- HBRUSH hbrBackground
Bu eleman pencerenin zemin rengini belirlemekte kullanılır. Bu elemana iskelet Windows programında GetStockObject fonksiyonuyla elde edilen değer atanmıştır.
GetStockObject(WHITE_BRUSH);

- LPCTSTR lpszMenuName
Program menuye sahip olabilir ya da olmayabilir. Eğer olacaksa buraya menu kaynağının ismi girilmelidir.

- LPCTSTR lpszClassName
Her WNDCLASS yapısının bir ismi vardır. Bu isim CreateWindows fonksiyonuna parametre olarak geçirilir. Yani aslında CreateWindow fonksiyonu bu isimden hareketle bu yapının içerisindeki bilgileri elde eder.
WNDCLASS yapısının içi doldurulduktan sonra bu yapının sisteme tanıtılması gerekir. Bu tanıtma işlemi RegisterClass API fonksiyonu ile yapılır. Bu API fonksiyonu WNDCLASS türünden bir yapı değişkeninin adresini parametre olarak alır. WNDCLASS yapısının sisteme tanıtılması işlemi 32 bit Windows sistemlerinde programın her kopyası için yapılmak zorundadır. Ancak 16 bit Windows sistemlerinde bu işlem yalnızca ilk kopya için yapılmalıdır. Bunu yapan kod 16 bit Windows sistemleriyle uyumu korumak için if (!hPrevInstance) { }kod bloğunun içinde yapılır. RegisterClass fonksiyonu WNDCLASS yapısına ilişkin bu bilgileri sistem bölgesine kopyalar. Herhangi bir API fonkiyonu isterse bu bilgilere ulaşabilir(Win32'de program sonlandırıldığında o programın sisteme tanıttığı bütün WNDCLASS bilgileri sistemden boşaltılır).










Programın Ana Penceresinin Yaratılması

Pencerenin yaratılması CreateWindow API fonksiyonu ile yapılır.

CreateWindow Fonksiyonunun Parametreleri

- LPCTSTR lpszClassName
Bu parametre daha önce sisteme tanıtılmış olan WNDCLASS yapısının ismini verir. Bu ismi alan CreateWindow sistem alanına ulaşarak sisteme tanıtılmış olan bütün yapılar arasından uygun olanı alır.

- LPCTSTR lpszWindowName
Pencerenin başlık yazısını belirlemek için kullanılır.

- DWORD dwStyle
Pencerenin görüntü biçimini belirlemekte kullanılır. Bu değişken 32 bitten oluşmaktadır. Her bit bir özelliğin olduğunu ya da olmadığını belirlemekte kullanılır. Pencere biçimlerine ilişkin windows.h içerisinde tanımlanmış WS_ ile başlayan bir grup sembolik sabit vardır. Bu sembolik sabitlerin yalnızca bir biti 1 diğer bitleri 0'dır. Bu sembolik sabitler bit OR işlemine sokularak çeşitli özelliklerin birlikte sağlanması için kullanılabilirler.

Başlıca Pencere Biçimleri

- WS_VISIBLE
Yaratılır yaratılmaz pencerenenin görüntülenmesini sağlar.
- WS_BORDER
Penerenin sınır çizgilerinin görünmesini sağlar.
- WS_CAPTION
Başlık kısmının olmasını sağlar.
- WS_SYSMENU
Sistem menüsünün görüntülenmesini sağlar.
- WS_OVERLAPPED
Pencerenin başlık kısmı ve sınır çizgilerinin olmasını sağlar.
- WS_OVERLAPPEDWINDOW
Windows.h içerisindeki bir sembolik sabit biçimindedir. WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX.
İskelet programda pencere biçimi olarak WS_OVERLAPPEDWINDOW olarak seçilmiştir. En sık kullanılan pencere biçimi budur.

- int x
int y
int nWidth
int nHeight
Pencerenin ekrandaki ilk araboyut(restore) koordinatlarıdır. x, y sol üst köşenin koordinatlarıdır. nWidth, nHeight yatay ve düşey uzunluklarıdır. İskelet programda bu değerler,
CW_USEDEFAULT
0
CW_USEDEFAULT
0
olarak girilmiştir. Pencerenin ilk görüntüsü masaüstünü ortalayacak biçimde yerleştirilir.

- HWND hWndParent
Pencereler üst pencere(parent window) ve alt pencere(child window) olmak üzere iki kısma ayrılır. Üst pencereler masa üstünde herhangi bir yere hareket ettirilebilirler. Oysa alt pencereler üst pencerelerin sınırları dışarısına çıkartılamaz. Alt pencerenin de alt penceresi olabilir(Aslında üst pencere masa üstünün alt penceresiymiş gibi de düşünülebilir). Aslında Windows'un push button, radio button, check box gibi görsel elemanları birer alt pencerdir. Bu tür özel alt pencerelere control denir. CreateWindow fonksiyonunun geri dönüş değeri HWND türündendir. Bu değere pencerenin handle değeri denir. Bir pencere yaratıldığında pencerenin bütün bilgileri sistem içerisinde gizli bir bölgeye aktarılır. Fonksiyon aslında bu bilginin aktarıldığı bölgenin başlangıç adresini verir. Pencereyle ilgili işlem yapan bütün API fonksiyonları bu handle değerini parametre olarak alırlar. Handle değerini alan API fonksiyonları ilgili pencerenin bütün bilgilerine erişebilir. Yani handle değeri hangi pencereyle ilgili işlem yapılacağını belirlemekte kullanılır. CreateWindow fonksiyonu hem üst pencere hem de alt pencere yaratılmasında kullanılmaktadır. Eğer üst pencere yaratılacaksa hWndParent parametresi NULL olarak, alt pencere yaratılacaksa hangi üst pencerenin alt penceresi olduğunu belirtmek için üst pencerenin handle değeri olarak girilmesi gerekir. İskelet programda üst pencere yaratılması söz konusu olduğu için NULL değeri girilmiştir.

- HMENU hMenu
Pencere menüye sahip olabilir. Eğer bu menü WNDCLASS yapısı içerisinde belirlenmemişse burada belirlenebilir. İskelet programda menü olmadığı için bu parametre NULL olarak girilmiştir.

- HANDLE hInstance
WinMain fonksiyonundan alınan hInstance değeri bu parametreye girilmelidir.

- LPVOID lpParam
Pencere yaratıldığında ek bir veri alanı oluşturmak istenebilir. Bu parametre bu alanın başlangıç adresini tutar. İskelet programda NULL olarak girilmiştir. Bu değer böyle bir alanın kullanılmayacağını belirtir.

CreateWindow Fonksiyonunun Geri Dönüş Değeri

Fonksiyonun geri dönüş değeri pencere başarılı bir biçimde yaratılmışsa pencerenin handle değeridir, başarısızlık durumunda fonksiyon NULL değeri ile geri döner. İskelet programda yaratılma işleminin başarısı kontrol edilmemiştir. Aslında bu işlemin başarısının kontrol edilmesi tavsiye edilir. Pencerenin yaratıldığında görüntülenip görüntülenmeyeceği pencere biçimindeki WS_VISIBLE parametresine bağlıdır. İskelet programda yaratılır yaratılmaz görüntülenmemektedir.




Yaratılmış Pencerenin Görüntülenmesi

Bir pencere WS_VISIBLE pencere biçimiyle yaratılmışsa yaratılır yaratılmaz zaten görüntülenir. Ancak değilse ShowWindow API fonksiyonu ile görüntülenir.

BOOL ShowWindow(HWND hWnd, int nExitCode);

Fonksiyonun birinci parametresi görüntülenecek pencerenin handle değeri, ikinci parametresi ise görüntülenme biçimidir. Görüntülenme biçimi SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE olabilir.
(Bir fonksiyonun geri dönüş değeri BOOL ise başarı bilgisinin verildiği anlaşılır. BOOL değer mantıksal olarak 0 ya da 0 dışı bir değer olarak değerlendirilir. Örneğin ShowWindow başarılı ise 1'e değil 0 dışı herhangi bir değere geri dönmektedir.)
Ana pencere yaratıldıktan sonra içsel görüntünün güncelleştirilmesi için WM_PAINT mesajı gerekebilir. Bunu sağlamak için UpdateWindow API fonksiyonu çağırılır.

İskelet Programın Aşamaları

Pencereli bir Windows programı tipik olarak 3 aşamadan geçilerek oluşturulur.

1. WNDCLASS yapısının içi doldurularak sisteme tanıtılması aşaması,
2. Pencerenin yaratılarak görüntülenmesi aşaması,
3. Mesaj dögüsünün oluşturulması ve pencere fonksiyonunun tasarımı.

Mesaj Kavramı

DOS işletim sisteminde klavye ve mouse bilgileri programcının koda yerleştirdiği fonksiyonlar yardımıyla elde edilir. Örneğin getchar() fonksiyonu klavyeden bir tuşa basılana kadar bekler, basılan tuşun bilgisini alarak işlemini sonlandırır. Oysa Windows sistemlerinde klavye ve mouse gibi giriş bilgileri programcının çağırdığı bir fonksiyonla değil, Windows sistemlerinin kendisi tarafından ilk elden alınır. Windows sistemlerinde sistem tarafından tespit edilen girdi bilgilerine mesaj denir. Her girdi bilgisinin yani mesajın hangi nedenden dolayı oluştuğunu açıklayan bir türü vardır. Örneğin mesaj klavyede bir tuşa basılmasından dolayı oluşmuş olabilir ya da mouse ile tek tıklama ya da çift tıklama sonucunda oluşmuş olabilir. Windows oluşan bu mesajı MSG yapısı biçiminde ifade ederek programın mesaj kuyruğuna yerleştirir. Her programın(32 bit Windows sistemlerinde aslında her alt işlemin) bir mesaj kuruğu vardır. Mesaj kuyruğu aslında MSG türünden bir yapı dizisi biçimindedir. MSG yapısı şöyledir:

typedef struct tagMSG { // msg
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;


MSG Yapısının Elamanları

- HWND hWnd
Her pencerenin bir mesaj kuyruğu yoktur. Her programın bir mesaj kuyruğu vardır. Yani bir program 10 tane pencere yaratmış olsa bile bu pencerelerin herhangi birisinde oluşan girdi işlemi aynı kuyruğa yazılacaktır. Yapının bu elemanı programın hangi penceresine ilişkin bir mesaj oluştuğunu belirtir.

- UINT message
Bu eleman mesajın hangi sebepten kuyruğa yazıldığını anlatan bir sayı içerir. Bir mesaj yüzlerce sebepten dolayı kuyruğa yazılabilir. Ancak mesajın nedenleri sayısal düzeyde konuşulmaz. Windows.h içerisinde tüm bu sayılar WM_ ile başlayan sembolik sabitlerle tanımlanmıştır. Yani örneğin 108 numaralı mesaj yerine WM_XXXXX mesajı biçiminde durum ifade edilir.

- WPARAM wParam
LPARAM lParam
WPARAM aslında unsigned int türüdür. Unsigned int türü 16 bit Windows sistemlerinde 2 byte uzunluğundaydı. Ancak 32 bit Windows sistemlerinde 4 byte'lık bir bilgidir. Burada W ön eki 16 bit Windows sistemleri kullanılırken isimlendirilmiştir. 32 bit sistemlere geçildiğinde bu isimlendirmenin kullanılmasına devam edilmiştir. LPARAM unsigned long türüdür ve her iki sistemde de 4 byte uzunluğundadır. Bu elemanlara mesaja bağlı olan ek bilgiler yerleştirilir. Örneğin WM_CHAR mesajında wParam basılan tuşun ASCII sıra numarasını içerirken WM_LBUTTONDOWN mesajında basılan noktanın koordinat bilgisini içermektedir. Her mesaj için bu elemanlara hangi bilgilerin yerleştirildiği ayrıca öğrenilmelidir.

- DWORD time
Mesajın gönderildiği zaman bilgisidir.

- POINT pt
Bu eleman bazı mesajlarda ekrana ilişkin koordinat bilgisini tutmak amacıyla kullanılır.

Mesaj Döngüsü

Mesajlar sistem tarafından kuyruğa yazılır, ancak bu mesajların alınarak işlenmesi programcı tarafından yapılır. Programcı mesajları alarak önce bu mesajları anlamlandırır, daha sonra uygun işlemleri yapacak kodları çalıştırır. Programa ilişkin pencere kapatılıp program sonlandırılacağı zaman bu işlem de Windows tarafından WM_QUIT mesajı olarak kuyruğa yazılır. Yani bir döngü içerisinde mesajların sürekli alınarak işlenmesi WM_QUIT mesajı görüldüğünde de döngü sonlandırılarak programın bitirilmesi gerekir.

GetMessage Fonksiyonu

GetMessage kuyrukta bulunan ilk mesajı alır ve bu mesajı kuyruktan siler. Fonksiyonun prototipi:


BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
);

Fonksiyonun birinci paranmertesi MSG türünden bir göstericidir. Bu parametreye MSG türünden bir yapının adresi geçirilmelidir. GetMessage kuyrukta sırada bulunan mesajı alarak bu yapının içerisine yerleştirir. İkinci parametre programa ilişkin hangi pencerenin mesajlarının alınacağını belirtir. Yani GetMessage ile özellikle bir pencereye ilişkin mesajlar alınabilir. Bu parametre NULL girilirse bütün pencerelere ilişkin mesajlar alınır. Fonksiyonun üçüncü ve dördüncü parametreleri hangi aralıktaki mesajların kuyruktan alınacağını belirtir. Örneğin bu parametrelere 100 ve 120 girilirse yalnızca bu aralıkta numaralara sahip olan mesajlar alınır. Eğer bu iki parametreye 0 girilirse tüm mesajların alınacağı anlamına gelir. İskelet programda tüm mesajlar alınmaktadır. Fonksiyon eğer WM_QUIT mesajını aldıysa 0 değerine, WM_QUIT dışındaki bir mesajı aldıysa 0 dışı herhangi bir değere geri döner. GetMessage eğer kuyrukta mesaj yoksa programın çizelgeleme dışı bırakılıp bloke edilmesine yol açar. Yani programcı bakış açısıyla programın akışı GetMessage içerisinde beklemektedir. Kuyruktan sürekli olarak mesajı alan WM_QUIT görünce işlemi sonlandıran bir döngü şöyle kurulabilir:

while (GetMessage(&msg, NULL, 0, 0)) {
...........
..........
.........
}

Mesaj döngüsünden çıkıldığında WinMain fonksiyonu da biter, bu fonkiyon bitince de program biter. GetMessage fonksiyonu ile mesaj alındıktan sonra anlamlandırılıp işlenmelidir, ancak prensip olarak mesajın mümkün olduğu kadar çabuk bir biçimde işlenmesi istenir. Eğer mesajın işlenmesi uzun sürerse GetMessage bir sonraki mesajı kuyruktan alamaz. Böylece programda herhangi bir ilerleme söz konusu olamaz. Ancak yine de mesajın işlenmesini geciktirecek ciddi sebepler olabilir. O zaman programın akışının devam etmesi nasıl sağlanacaktır? İşte alt işlemli programlama sistemi(multi-threading) bu tür problemlere çözüm bulmaktadır.

Mesajların İşlenmesi ve Pencere Fonksiyonu

Mesajların işlenmesi ismine pencere fonksiyonu denilen bir fonksiyon tarafından yapılır. Kuyruktan mesaj alındığında DispatchMessage API fonksiyonu çağırılır. DispatchMessage fonksiyonuna parametre olarak kuyruktan alınan mesajın bulunduğu değişkenin adresi geçirilmektedir. DispatchMessage mesajın hWnd elamanına bakarak mesajın hangi pencereye ilişkin olduğunu anlar. O pencere ilişkin pencere fonksiyonunu çağırır. Bir pencere yapısının parametrik yapısı şöyle olmak zorundadır:





LRESULT CALLBACK WndProc(
HWND hWnd,
UINT message
WPARAM wParam
LPARAM lParam
);

Fonksiyonun geri dönüş değeri LRESULT yani long olmak zorundadır. Çağırma biçimi __stdcall olmak zorundadır. Zaten CALLBACK sembolik sabiti __stdcall anlamına gelmektedir. DispatchMessage fonksiyonu mesajı alıp mesaj içerisindeki hWnd, message, wParam, lParam elemanlarını ayrıştırarak bu elemanları pencere fonksiyonunun parametresi yapmak suretiyle pencere fonksiyonunu çağırır. Yani programın akışı pencere fonksiyonumuzdan çıktığında akış DispatchMessage içerisinden devam eder.
Mesaj döngüsünün içerisinde TranslateMessage API fonksiyonu da çağırılmaktadır. Bu fonksiyonun mesaj işlenme mekanizmasıyla ciddi bir bağlantısı yoktur. ASCII tuşlarına basıldığında WM_CHAR mesajının oluşumunu sağlar.

Pencere Fonksiyonunun Tasarımı

Bunun için önce mesajın ne mesajı olduğunun tespit edilmesi gerekir. Bu işlem bir switch deyimiyle yapılabilir. Daha sonra mesaj parametreleri yorumlanarak case ifadeleri işlenir.

Windows Programının Sonlandırılması

Bir Windows programı programın akışı mesaj döngüsünden çıkıp WinMain fonksiyonunun bitmesiyle sonlanır. Program akışının mesaj döngüsünden çıkması GetMessage fonksiyonunun 0 ile geri dönmesiyle sağlanır. GetMessage fonksiyonu WM_QUIT mesajını gördüğünde 0'a geri döner.

DefWindowProc API Fonksiyonu

Bir programın en basit işlemleri yapacak biçimde sağlıklı çalışabilmesi için bir takım kritik mesajların işlenmesi gerekir. Oysa bunların işlenmesi ve bu mesajlara karşılık default bazı işlemleri yapılması uzun bir işlem yükü gerektirir. İşte DefWindowProc fonksiyonu bir mesaj için default kritik işlemleri yapabilen bir fonksiyondur. Yani pencere fonksiyonu içerisinde mesajlar işlenir, işlenmeyen mesajlar bu API fonksiyon çağırılarak işletilir. O halde en basit bir pencere fonksiyonu şöyle tasarlanabilir:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT, message, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, message, wParam, lParam);
} /*Tüm mesajlar default olarak işlenecektir*/

DefWindowProc fonksiyonunun gelen mesajlara karşı hangi kritik işlemleri yaptığı bazı tür işlemlerde programcı tarafından bilinmek zorundadır.
İşlenen mesajlar için DefWindowProc fonksiyonu çağırılmamalıdır. O halde bu fonksiyon tipik olarak switch'in default kısmına yerleştirilmelidir.

Pencere Fonksiyonunun Geri Dönüş Değeri

Pencere fonksiyonunun geri dönüş değeri DispatchMessage fonksiyonu tarafından yorumlanır. Fonksiyonun geri dönüş değeri mesajdan mesaja değişir. Yani hangi mesaj geldiğinde neyle geri dönüleceği önceden bilinmek zorundadır. Ancak aksi söylenmediği sürece pencere fonksiyonu eğer mesajı işlemişse 0 ile geri dönmelidir. İşlememişse DefWindowProc fonksiyonunun geri dönüş değeriyle geri dönmelidir.

LRESULT CALLBACK WindowProc(HWND hWnd, UINT, message, WPARAM wParam, LPARAM lParam);
{
switch(message) {
case .......... :
........
........
break;
case .......... :
........
........
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

Pencerenin Kapatılması Sırasında Gerçekleşen İşlemler

Bir pencereye kapatmak için klik yapıldığında ya da klavye ile Alt+F4 tuşlarına basıldığında Windows yalnızca mesaj kuyruğuna WM_CLOSE mesajını bırakır. Bu mesaja karşılık DefWindowProc DestroyWindow API fonksiyonunu çağırmaktadır. Bu API fonksiyonu pencereyi kapar ve mesaj kuyruğuna WM_DESTROY mesajını koyar. WM_DESTROY mesajı genellikle programcı tarafından işlenir. Programcı bu mesaj karşılığında PostQuitMessage API fonksiyonunu çağırmalıdır(zaten DefWindowProc fonksiyonu da default olarak PostQuitMessage fonksiyonunu çağırır), bu fonksiyon yalnızca kuyruğa WM_QUIT mesajını yerleştirir. GetMessage fonksiyonu da bu mesajı alarak 0 ile geri döner ve WinMain sonlanır.


Visual C++ Geliştirme Sisteminin Kullanılması

Windows altında geliştirme ortamlarında programlama sistemi karmaşık olduğu için mutlaka proje dosyası oluşturularak çalışılır. Uygun bir proje dosyası oluşturabilmek için File => New seçilir. Eğer Win32 Console Application seçilirse konsol programı yazılabilir. Bir konsol programı tamamen DOS'teki bilgilerle yazılabilir. Ancak Windows'un grafik özellikleri kullanılamaz. Eğer Win32 Application seçilirse API düzeyinde programlama yapılabilir. 6.0 sürümünde iskelet programı oluşturan bir wizard da yerleştirilmiştir. Tüm projeler için ayrı bir dizin açılır ve proje dosyaları o dizin içerisine yerleştirilir. Dizin proje ismiyle aynı isimde olur. Açılan dizin içerisine projedeki bütün kaynak dosyalar yerleştirilir. Proje dizininin altında res ve debug/release isimli iki dizin oluşturulur(bu genellikle debug olur, program kaynak kullanmamışsa res dizini açılmaz). Res dizini içerisinde kaynak kullanımına ilişkin dosyalar bulunur. Debug/release'in içerisinde bütün obj modüller, exe dosyaları ve precompiled header dosyası bulunur. Precompiled header dosyası başlık dosyalarını çabuk analiz etmek için gerekir, çok büyük bir dosyadır. Bir projeyi diskete almak için önce debug/release dizini silinmeli ve proje tüm alt dizinleriyle beraber alınmalıdır. Bir proje yaratıldığında bütün proje işlemleri ismine proje çalışma alanı(project workspace) denilen bir pencere yardımıyla yürütülür. Proje çalışma alanı penceresi kapatılabilir(projenin kapandığı anlamına gelmez), daha sonra Alt+0 tuşları ile açılabilir. Bir projenin tamamen kapatılması için File=>Close Workspace seçilmelidir. Proje çalışma alanı penceresinin 4 alt penceresi vardır.

Class View: Burada bütün C++'taki sınıflar C'deki fonksiyonlar listelenir. Buradaki bir elemanın üzerine double click yapılırsa o fonksiyonun tanımlamasının bulunduğu yere gidilebilir.
File View: Burada projenin içindeki dosyaların listesi bulunur. Bu pencere aynı zamanda projeye dosya eklemek ve projeden dosya çıkarmak için de kullanılır. Eklemek için projenin üzerinde sağ fare tuşuna basılıp Add Files To Project seçilerek yapılır.
Resource View: Bu pencere program kaynak kullanıyorsa yaratılır. Kaynak işlemleri bu pencereden izlenebilir.
Info View: Yardım almakta kullanılır.


Programın Derlenmesi ve Çalıştırılması

Editördeki program Build=>Compile menüsüyle derlenir(Ctrl+F7). Proje içerisindeki bütün dosyaları ve kaynak dosyasını derleyip hep beraber link ederek exe yapmak için Build=>Build seçilir(F7). Bu seçenek yalnızca değişmiş olan dosyaları yeniden derler. Koşulsuz bütün dosyaları derleyip exe yapmak için Build=>Rebuild seçilir. Bir programı çalıştırmak için Build=>execute seçilir(Ctrl+F5). Tabii değişen dosyalar bu arada tekrar derlenir. Bir projeyi açmak için File=>Open Workspace.
Bir fonksiyonun pencere fonksiyonu olduğunu belirtmek için o fonksiyon isminin WndClass yapısının lpfnWndProc elemanına yazılması gerekir.




Windows Programlamada Yardım İşlemleri

Windows altında programlama için iyi bir yardım desteğinin olması gerekir. Visual C++ geliştirme ortamının Online Book diye isimlendirilen bir yardım desteği vardır. Visual C++ 6.0 sürümünde yardım desteği MSDN programının ayrıca install edilmesiyle sağlanır. Online Book içerisinde sistemin orijinal kitapları bulundurulmaktadır.

Mouse Mesajları

Bir pencerenin başlık kısmı çıkartılmış bölgesine çalışma alanı(client area) denir. Çalışma alanının sol üst köşegeni pek çok işlem için orijin noktası belirtir. Mouse pencerenin çalışma alanı içerisinde bir yerde tıklandığında ve çekildiğinde Windows mesaj kuyuruğuna WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONUP mesajlarını ekler. Bu mesajların lParam ve lParam parametreleri şu bilgileri içerir:
wParam: Click yapıldığında aynı zamanda bir tuşa basılıp basılmadığını belirtir. Şunlardan oluşur:

MK_CONTROL
MK_LBUTTON
MK_RBUTTON
MK_MBUTTON
MK_SHIFT

lParam: Mouse'un click yapıldığı pixel pozisyonudur.
xPos = LOWRD(lParam);
yPos = HIWORD(lParam);

LOWORD ve HIWORD makroları 32 bit bir bilginin yüksek anlamlı ve düşük anlamlı 2 byte'ını elde etmek için kullanılır.
#define HIWORD(x) ((WORD) (x) >> 16)
#define LOWORD(x) ((WORD) (x))
Bu makrolar windows.h içerisinde tanımlanmıştır.

MessageBox Fonksiyonu

Windows'ta acil bir mesaj basmak için MessageBox API fonksiyonu kullanılır. Bu fonksiyon ile pencere başlığı, pencerenin içerisindeki mesaj, istenen tuş takımı ve görüntülenecek ikon belirlenebilir.

int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption
UINT uType
);

Fonksiyonun birinci parametresi messagebox penceresinin çıkartılacağı üst pencerenin handle değeridir. Bu parametre NULL olarak girilebilir(messagebox yaratmak için bir pencere yaratmak gerekli değildir). Yani programın hiçbir pencereyi olmasa bile messagebox çıkartılabilir. İkinci parametresi pencerenin içine yazılacak yazının başlangıç adresini alır. Üçüncü parametresi pencerenin başlık yazısını belirtir. Dördüncü parametresi tuş takımı ve ikon görüntüsünü belirler. Tuş takımları şunlar olabilir:

MB_ABORTRETRYIGNORE
MB_OK
MB_OKCANCEL
MB_YESNO
MB_YESNOCANCEL

İkon görüntüsü şunlar olabilir:

MB_ICONEXCLAMATION
MB_ICONWARNING
MB_ICONINFORMATION
MB_ICONASTERIKS
MB_ICONQUESTION
MB_ICONSTOP

Tuş takımıyla ikon görüntüsü bit OR işlemine sokularak birleştirilebilir. Örneğin: MB_OK | MB_ICONEXCLAMATION
Tuş takımlarından bir tanesi default olarak seçilebilir. Default tuş enter tuşuna basıldığında seçilmiş kabul edilen tuştur. Default tuşu belirlemek için 3 tane sembolik sabit vardır:

MB_DEFBUTTON1
MB_DEFBUTTON2
MB_DEFBUTTON3

Bu sembolik sabitler de diğerleriyle birleştirilerek kullanılırlar. Örneğin:
MB_YESNOCANCEL | MB_ICON_EXCLAMATION | MB_DEFBUTTON3

Fonksiyonun geri dönüş değeri hangi tuşa basılarak pencerenin kapatıldığı bilgisini verir. Şunlardan bir tanesi olabilir:

ID_ABORT
ID_CANCEL
ID_IGNORE
ID_NO
ID_OK
ID_RETRY
ID_YES

Mouse'un sol tuşuna basıldığında messagebox çıkartan uygulama:






LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd, "Deneme", "Deneme", MB_YESNOCANCEL | MB_ICONSTOP | MB_DEFBUTTON2);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}

Sınıf çalışması: Farenin sol tuşuna basıldığında yesnocancel messagebox'ı gözükecek, bunlardan bir tanesi seçildiğinde başka bi messagebox ile hangi tuş'a basıldığı yazdırılacak.

LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
iMsgBoxReturnValue = MessageBox(hwnd, "Deneme yapıyom ben", "Deneme dedik aşşaada", MB_YESNOCANCEL | MB_ICONSTOP | MB_DEFBUTTON2);
switch (iMsgBoxReturnValue) {
case IDYES:
MessageBox(hwnd, "Yes'e bastın kardeş", "Deneme", MB_OK | MB_ICONSTOP);
break;
case IDNO:
MessageBox(hwnd, "No'ya bastın kardeş", "Deneme", MB_OK | MB_ICONSTOP);
break;
case IDCANCEL:
MessageBox(hwnd, "Cancel'a bastın kardeş", "Deneme", MB_OK | MB_ICONSTOP);
break;
}
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}

DestroyWindow Fonksiyonu

CreateWindow fonksiyonu pencereyi yarattıktan sonra pencereye ilişkin bütün bilgileri dinamik olarak tahsis ettiği içsel bir yapıda saklar. Aslında CreateWindow fonksiyonunun vermiş olduğu bu geri dönüş değeri bu içsel yapının başlangıç adresidir. DestroyWindow fonksiyonu pencereyi ekrandan görüntüsel olarak siler ve CreateWindow fonksiyonu tarafından dinamik olarak oluşturulmuş olan bu içsel yapıyı da free hale getirir. DestroyWindow fonksiyonu DefWindowProc tarafından WM_CLOSE mesajına karşı otomatik olarak çağırılır. Tabii istenildiği zaman programın ana penceresi kapatılmak isteniyorsa DestroyWindow programcı tarafından çağırılmalıdır. DestroyWindow pencere görüntüsü ekrandan sildikten sonra programcıyı haberdar etmek için WM_DESTROY mesajını gönderir. DestroyWindow aynı zamanda pencerenin bütün alt pencerelerini de DestroyWindow fonksiyonunu çağırarak siler. WM_DESTROY mesajı geldiğinde pencere ve alt pencereler ekranda görünür değildir, ancak bunlara ilişkin veri yapıları hala durmaktadır.

BOOL DestroyWindow(HWND hWnd);

Fonksiyon silinecek pencerenin handle değerini parametre olarak alır.

WM_CREATE Mesajı

Bu mesaj CreateWindow fonksiyonu tarafından pencerenin yaratıldığını bildirmek amacıyla gönderilir. Pencere yaratıldığında yapılmak istenen ilk işlemler WM_CREATE mesajı işlenerek yapılabilirler. WM_CREATE mesajı gönderildiğinde pencere henüz görünür değildir(henüz CreateWindow fonksiyonundan çıkılmamıştır). lParam parametresinde CREATESTRUCT isimli bir yapının adresi bulunur. Bu yapının içi CreateWindow tarafından doldurulmuştur ve faydalı bilgiler içermektedir. Bu yapı içerisindeki bilgilere şu biçimde erişilebilir:

case WM_CREATE:
{
CREATESTRUCT *pStruct;
pStruct = (LPCREATESTRUCT ) lParam;
.............
.............
.............
}
break;

SendMessage ve PostMessage Fonksiyonları

Mesaj kuyruğuna mesajlar PostMessage fonksiyonuyla programcı tarafından bilinçli olarak da bırakılabilirler. Tabii bu mesaj normal olarak kuyruğun sonuna bırakılırlar. Mesajın kuyruğa bırakılmasıyla işlenmesi arasında belli bir zaman kaybı söz konusu olabilir. Yani PostMessage fonksiyonu pencere fonksiyonu içerisinde kullanıldığında programın akışı PostMessage fonksiyonundan çıkar, mesaj kuyruğuna girilerek sıradaki mesajlar işlenir. En sonunda kuyruğa PostMessage ile programcı tarafından bırakılan mesaj alınarak işlenir. Oysa SendMessage fonksiyonu mesajı kuyruğa bırakmaz, doğrudan pencere fonksiyonunu çağırarak hemen işler. Yani programın akışı SendMessage'den çıktığında mesaj işlenmiş olur. Her iki fonksiyonun da parametrik yapısı aynıdır.




LRESULT SendMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);

BOOL PostMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);

Fonksiyonların birinci parametresi mesajın gönderileceği pencerenin handle değeridir. Yani bu fonksiyonlar bu handle'a ilişkin pencerenin yaratılması sırasında belirtilen pencere fonksiyonunu çağırırlar. Fonksiyonların ikinci parametresi gönderilecek mesajın numarasıdır. Üçüncü ve dördüncü parametreler mesajın wParam ve lParam parametreleridir. PostMessage fonksiyonunun geri dönüş değeri BOOL türündendir, işlemin başarısını bildirir. Oysa SendMessage fonksiyonunun geri dönüş değeri çağırılan pencere fonksiyonunun geri dönüş değeridir.

Kaynakların Program İçerisinden Kullanılması

Normal olarak kaynaklar rc uzantılı bir text dosyası içerisine kaynak dili kullanılarak yazılırlar. Kaynak derleyicisi tarafından derlenip res uzantılı yapılırlar ve linker tarafından PE formatındaki exe dosyanın içindeki kaynak bölümüne yerleştirilirler. Visual C++ geliştirme sisteminde rc dosyası proje dosyasına eklenirse bu işlemler otomatik olarak yapılır.
Her kaynağın kaynak dilinde nasıl yazılacağı önceden belirlenmiştir ve belli bir syntax kuralı vardır. Ancak kaynakların programcı tarafından bu biçimde yazılması, yani kaynak dilinin öğrenilmesi çok zahmetlidir. Bunun için tüm geliştirme sistemlerinde kaynaklar ismine kaynak editörü(resource editor) denilen bir ortamda görsel olarak hazırlanırlar. Kaynaklar görsel olarak belirlendikten sonra geliştirme sistemi bunun kaynak dilindeki karşılığını rc dosyası biçiminde oluşturur. Her kaynağın bir ismi vardır. Bu isim alfabetik ya da sayısal biçimde verilebilir. Eğer kaynak isminin ilk harfi alfabetik bir karakterle başlıyorsa kaynak alfabetik olarak isimlendirilmiştir, sayısal bir karakterle başlıyorsa kaynak sayısal olarak isimlendirilmiştir(Eğer bir sayı alfabetik bir isim olarak kullanılacaksa çift tırnak içine alınmalıdır). Genel olarak sayısal biçimde isimlendirilmiş kaynaklar ile daha hızlı işlem yapılır. Bir kaynağı bir programın içinde kullanmak için kaynağı hazır hale getirmek gerekir. Bu işlem sırasında kaynak exe dosyanın kaynak bölümünden alınır, bellekte dinamik olarak yaratılan bir veri yapısının içerisine çekilir. kaynağı hazır hale getiren fonksiyonların isimleri Loadxxxx biçimindedir. Kaynağı hazır hale getiren Loadxxxx fonksiyonlarının iki parametresi vardır. Birincisi exe dosyanın bellekteki yükleme adresi olan hInstance adresidir, ikincisi ise kaynağın ismidir(Bu fonksiyonların exe dosyasının kaynak bölümüne erişebilmesi için exe dosyasının bellekteki yükleme adresini bilmeleri gereklidir). Loadxxxx fonksiyonlarının geri dönüş değerleri kaynağa ilişkin handle değerleridir. Örneğin HCURSOR, HICON, HMENU biçiminde olabilir(hepsi aslında void *).


Menü Kaynağının Kaynak Dilinde Oluşturulması

Kaynak dilinde her kaynak önce kaynak ismiyle başlar, sonra onu kaynağın türünü belirten bir anahtar sözcük izler, sonra kaynaklara göre değişebilen parametrik bilgiler yazılır. Bir menü menü çubuğu ve popup menülerden oluşur. Popup menünün içerisinde başka bir popup menü bulunabilir. Bir menü popup menülerden, popup menüler de menü elemanlarından oluşur. Kaynak derleyicileri C'nin ön işlemci komutlarını aynı biçimde kullanabilir. Popup menülerin bir numarası yoktur ama her menü elemanının bir numarası olmak zorundadır. Menü elemanlarının numaraları istenildiği gibi seçilebilir(Ancak 100'den büyük olması tavsiye edilir). Ancak her menü elemanının numarası diğerinden farklı olmalıdır.
Kaynak dilinde yazılmış kaynaklar çeşitli sayılar kullanabilirler. Bu sayıların ayrı bir başlık dosyasında sembolik sabit olarak tanımlanmaları önerilmektedir. Bu durumda kaynak kullanımı için bir rc dosyası, bir de h dosyası oluşturulur. Bu rc dosyası içerisinden h dosyası include edilir. Örneğin Visual C++ geliştirme sisteminde bir kaynak dosyası yaratıldığında otomatik olarak resource.h dosyası da yaratılır.

Menü Kaynağının Program İçerisinden Kullanılması

Bir menü kaynağını programa dahil edebilmek için üç yöntem vardır:

1. WNDCLASS yapısının lpszMenuName elemanına menü kaynak ismi girilirse menü otomatik olarak görüntülenir.
2. WNDCLASS yapısının lpszMenuName elemanı NULL olarak girilirse menü yine de CreateWindow fonksiyonunda yaratılabilir. Bunun için önce LoadMenu fonksiyonuyla menü kaynağı hazırlanır, sonra buradan alınan handle değeri CreateWindow fonksiyonunun hMenu parametresi olarak verilir.

HMENU hMenu;
hMenu = LoadMenu(hInstance, "SAMPLE_MENU");
CreateWindow(.........................., hMenu, ......);

3. Menü CreateWindow fonksiyonundan sonra programın herhangi bir yerinde SetMenu API fonsiyonuyla da yaratılabilir.

Alt Pencerelerle İşlemler

Alt pencereler CreateWindow fonksiyonuyla yaratılırlar. Verilen koordinatlar üst pencerenin çalışma alanı(client area) referans alınarak oluşturulurlar(Üst pencerelerin referans noktası masaüstü penceresinin sol üst köşesidir). Alt pencere yaratılırken üst pencerenin handle değerine gereksinim duyulur. Alt pencerelerin handle değerlerinin yanısıra bir de id değerleri vardır. Alt pencere id değerleri işaretsiz tam sayı biçimindedir ve normal olarak WORD sınırları içerisindedir. CreateWindow fonksiyonunun dokuzuncu parametresi HMENU türündendir. HMENU parametresi üst pencerelerde menü işlemleri için kullanılırken, alt pencerelerde pencere id değerinin belirlenmesi amacıyla kullanılır. Tabii bu parametrenin alt pencere id'si olarak girilmesi durumunda tür dönüştürmesi yapılması gerekir. Örneğin (HMENU) 100, ya da sembolik olarak (HMENU) CHILD_ID. Pencere id değeri WORD sınırlarında sıfırdan farklı herhangi bir değer olabilir. Alt pencerelerin id değerleri aslında tamamen programlamayı kolaylaştırmak amacıyla düşünülmüştür. Hem handle değeri hem de id değeri her ikisi de bir pencereyi teşhis etmek amacıyla kullanılabilir. Ancak id değerinin tam sayı türünden olması programlamada çeşitli biçimlerde kolaylık sağlamaktadır. Zaten alt pencerenin handle değeriyle id değerinin bir tanesinin bilinmesi durumunda diğerinin elde edilmesini sağlayan API fonksiyonları vardır. Alt pencerelerin ve üst pencerelerin farklı pencere fonksiyonları olabilir. Alt pencereyle üst pencerenin pencere fonksiyonlarının farklı olabilmesi için bu iki pencerenin farklı WNDCLASS yapılarıyla yaratılması gerekir. Çünkü pencere fonksiyonunun belirlenmesi WNDCLASS ile yapılmaktadır. Bir program içerisinde ne kadar çok alt pencere ve üst pencere yaratılmış olursa olsun bu pencerelere ilişkin mesajlar programın(aslında alt işlemin(thread)) mesaj kuyruğuna yerleştirilirler. Yani her programın(aslında alt işlemin) yalnızca bir tane mesaj kuyruğu vardır, o programın yarattığı bütün pencerelere ilişkin mesajlar aynı kuyruğa yerleştirilir. Programın tek bir mesaj döngüsü vardır. GetMessage fonksiyonu tüm pencereler için gönderilmiş olan mesajları alabilmektedir. Mesaj karşılığında hangi pencere fonksiyonunun çağırılacağı kararı DispatchMessage fonksiyonu tarafından verilir. DispatchMessage fonksiyonu mesajın hWnd parametresine bakarak pencerenin hangi WNDCLASS yapısıyla yaratılmış olduğunu tespit eder ve buradan ilgili pencere fonksiyonunu bularak çağırır. DestroyWindow fonksiyonu ile üst pencere yok edilince DestroyWindow fonksiyonu önce alt pencereleri yok eder, daha sonra ilgili pencereyi yok eder.

Uyarı: DefWindowProc fonksiyonu WM_CLOSE mesajı işlenmemişse default olarak DestroyWindow fonksiyonunu çağırır. Ancak WM_DESTROY için PostQuitMessage'i çağırmaz. Eğer WM_DESTROY mesajı ile PostQuitMessage çağırılmamışsa pencere silinir ama program sonlanmaz.

Üst ve Alt Pencereler Arası Mesaj Alış-Verişi

SendMessage ve PostMessage fonksiyonlarıyla üst pencere alt pencereye, alt pencere de üst pencereye mesaj gönderebilir. Aslında bu fonksiyonlarla handle değeri bilindikten sonra her türlü pencereye mesaj gönderilebilmektedir.

Alt Pencere Nerede Yaratılmalı?

Alt pencere üst pencere yaratıldıktan sonra herhangi bir yerde yaratılabilir. Ancak uygulamalarda bu işlem genellikle iki biçimde yapılır:
1. Önce CreateWindow ile üst pencere yaratılır. Bu kodun aşağısında yine CreateWindow ile alt pencere yaratılır.
2. Alt pencere üst pencerenin pencere fonksiyonu içerisinde WM_CREATE mesajında yaratılır. Tabii burada hInstance değerinin WinMain fonksiyonundan bir biçimde elde edilmesi gerekir. hInstance değerinin herhangi bir yerden elde edilmesi için birkaç yöntem vardır. En fazla kullanılan yöntem bu değerin WinMain içerisinde global bir değişkene taşınmasıdır.

WM_USER Mesajları

Windows'un önceden belirlenmiş olan WM_ mesajları 0 ile 0x0400 arasında bulunmaktadır. Ancak programcı isterse kendi mesaj numaralarıyla da işlem yapabilir. Bunun için windows.h içerisinde tanımlanmış olan WM_USER değerinden 0x7FFF'e kadar olan mesajlar kullanılmalıdır. WM_USER sistem tarafından işlenen bir mesaj değildir. Yalnızca programcının kullanabileceği mesaj numarasının nereden başlayacağını anlatan bir sembolik sabittir.

Alt Pencere Biçimleri

CreateWindow fonksiyonunun ikinci parametresi olan pencere biçimi eğer alt pencere söz konusuysa en azından WS_CHILD içermelidir. Ancak WS_BORDER eklenmezse pencerenin sınır çizgisi görünmez. Genellikle alt pencereler için başlık kullanılmaz. Ancak WS_CAPTION pencere biçimi eklenirse pencere başlık kısmına sahip olabilir.

WS_VISIBLE Pencere Biçimi

İster üst pencere ister alt pencere söz konusu olsun eğer pencere biçimi olarak WS_VISIBLE seçilirse pencere yaratılır yaratılmaz pencere görüntülenir. Eğer WS_VISIBLE kullanılmazsa görüntüleme işlemi için ShowWindow fonksiyonunun çağırılması gerekir.
GetClientRect API Fonksiyonu

Bir pencereyle ilgili işlem yapılırken örneğin alt pencere koordinatlarının belirlenmesi ya da çizimler söz konusu olduğunda orijin noktası çalışma alanının(client area) sol üst köşesidir. Pencere boyutunun değiştirilmesi durumunda çalışma alanının sağ alt köşegeninin koordinatları da değişir. GetClientRect fonksiyonu çalışma alanının sağ alt köşegeninin koordinatlarını elde etmekte kullanılır. Bu koordinatın elde edilmesiyle pencerenin genişlik ve yükseklik bilgisi elde edilmiş olur. Prototipi:

BOOL GetClientRect(
HWND hWnd,
LPRECT lpRect
);

Kullanımı:
LPRECT rect;
GetClientRect(hWnd, &rect);

Fonksiyonun ikinci parametresi RECT türünden bir yapı değişkeninin adresini alır. RECT yapısı windows.h içerisinde şöyle bildirilmiştir:

typedef struct tagRECT{
long left, top, right, bottom;
} RECT *LPRECT;

GetClientRect fonksiyonu ile elde edilen dikdörtgensel koordinatın sol üst köşegeni her zaman 0, 0 olur. Zaten bu fonksiyon sağ alt köşegenin elde edilmesi için kullanılır.

WM_SIZE Mesajı

Windows bir pencerenin boyutunun değiştirildiği bir durumda mesaj kuyruğuna bu mesajı bırakır. Pencerenin boyutu köşe noktalarından mouse ile çekildiğinde ya da maximize, minimize, restore tuşlarına basıldığında değişmektedir. Mesajın wParam ve lParam parametreleri şöyle yerleştirilir:
Width = LOWORD(lParam); /*rect.right*/
Hight = HIWORD(lparam); /*rect.bottom*/

wParam parametresi şu değerleri alabilir:
SIZE_MINIMIZED
SIZE_MAXIMIZED
SIZE_RESTORED

MoveWindow API Fonksiyonu

CreateWindow fonksiyonu ile belirlenen koordinat pencerenin ilk açılma görüntüsüne ilişkindir. Bunun dışında pencerenin boyutu çeşitli biçimlerde değiştirilebilir. MoveWindow fonksiyonu hem pencerenin boyutunu değiştirmekte hem de onu ötelemekte kullanılabilir. Prototipi:

BOOL MoveWindow(
HWND hWnd,
int x,
int y,
int nWidth,
int nHeight,
BOOL bRepaint
);

Fonksiyonun birinci parametresi ilgili pencerenin handle değeri, x, y, nWidth ve nHeight parametreleri pencerenin yeni konumunun bilgileridir. Fonksiyonun son parametresi taşınan pencerenin görüntüsünün güncellenmesiyle ilgilidir. Bu parametre genellikle TRUE olarak verilir. Bu durumda güncelleme işlemi hemen yapılır.

Kontroller

Windows sistemi tarafından tanımlanmış olan bir grup alt pencere sistemine kontrol denir. Kontroller; temel kontroller ve gelişmiş kontroller biçiminde ikiye ayrılır. Temel kontroller şunlardır:

Static kontrolü
Push button kontrolü
Edit box kontrolü
List box kontrolü
Check box kontrolü
Radio button kontrolü
Combo box kontrolü
Scroll bar kontrolü

Gelişmiş kontroller şunlardır:

Toolbar kontrolü
Tree kontrolü
Status bar kontolrü
Proggress bar kontrolü
Column kontrolü
Property sheet kontrolü
Tab kontrolü
...

Windows sistemi yüklenirken bir grup WNDCLASS yapısını çeşitli isimlerle sisteme register eder. Bu sınıf isimleri alt pencere yaratmakta kullanılırsa pencere fonksiyonu sınıf ile belirtilen fonksiyonlar olur. Bu sınıfların pencere fonksiyonları user32.dll içerisindedir ve programcıdan gizlenmiştir. Bu sınıflar kullanılarak alt pencere yaratıldığında bu pencere için gönderilen mesajlar programcının değil bu sınıfların pencere fonksiyonu tarafından işlenir. Örneğin kontrol sınıflarına ilişkin bir pencere yaratılıp mouse ile üzerine click yapılsa mouse mesajı programın mesaj kuyruğuna bırakılacak ancak DispatchMessage kotrolün pencere fonksiyonunu çağıracaktır.

Static Kontrolü

Bu kontrol yalnızca bir alt pencerenin üzerine yazı görüntülemek için kullanılır. Static kontrol penceresinin zemin ve yazı renkleri ileride ele alınacaktır. Static kontrol penceresinin zemin rengiyle üst pencerenin zemin rengi aynı alınırsa bu kontrol bir pencereye yazı yazmak amacıyla kullanılır. Bu kontrolü yaratmak için CreateWindow fonksiyonunda sınıf ismi yerine "static" girilir. Pencere kordinatları yazının yazılacağı pencerenin koordinatlarıdır. Pencerenin içerisine yazılacak yazı CreateWindow fonksiyonunun pencere başlığı yazısıdır.
(WM_SIZE mesajı bir pencere ilk kez görüntülendiği zaman da gönderilmektedir.)

Static Kontrolünün Özel Pencere Biçimleri

Her pencere için ortak olan pencere biçimlerinin yanı sıra her kontrolün ayrı yalnızca o kontrol için anlamlı olan özel pencere biçimleri de vardır. Static kontrolü için en önemlileri şunlardır:

SS_LEFT
SS_RIGHT
SS_CENTER /*Bunlar yazının hizalanmasına ilişkindir.*/
SS_WHITERECT
SS_BLACKRECT
SS_GRAYRECT /*Bunlar static kontrolünün zemin rengine ilişkindir.*/
Ancak bu renkler mutlak değil göreli renklerdi

SAYGILAR=STING

0.45 Snitz Forums 2000