Windows İşletim Sisteminin Özellikleri
Windows'un Tarihi
Windows üzerinde ilk
çalışmalara 1985 yılında başlamıştır. İlk ürün Windows 1.0 idi. Windows 3.0
sürümü ile işletim sistemine benzeyen özellikler kazanmıştır. Windows'un en
uzun süre pazarda kalan sürümü 3.1'dir. Windows 3.1 kadar(3.1 dahil) Windows
sistemleri 16 bit mikro işlemcilerde çalışabilecek biçimdeydi. 1995'te Windows
95 piyasaya sürüldü ve bunu Windows 98 izledi. Win95/98/NT sistemleri 32 bitlik
Windows sistemleridir. 32 bit Windows sistemleri birbirine çok benzer
sistemleridir. Programlama bakımından bu sistemlerin hepsi yüksek düzeyde
uyumludur(.obj ve .exe dosyaları da tamamen uyumludur). Windows sistemleri
yalnızca Intel tabanlı mikro işlemciler için düşünülmemiş. Çeşitli risc tabanlı
sistemlerde de Windows işletim sistemi kullanılabilmektedir. Windows CE,
Windows sisteminin küçültülerek el bilgisayarlarına uyarlanmış biçimidir. Bu
sistemin programlama biçimi diğer Windows sistemleriyle uyumludur.
Windows Sisteminin Temel Özellikleri
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 cbClsExtra
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.
0 Yorumlar
Bizimle fikirlerinizi paylaşabilirsiniz.