Scroll Bar Kontrolünin Kullanımı
klavye |
Yapılacak ilk iş
SetScrollRange fonksiyonuyla scroll bar için mantıksal bir skala belirlemektir.
Bu işlem örneğin WM_CREATE mesajı içerisinde yapılabilir. Prototip:
Fonksiyonun birinci
paremetresi hangi pencereye ilişkin scroll bar işlemi uygulanacağıdır. Eğer
gömülü scroll bar söz konusuysa ana pencerenin handle'ı geçirilmelidir. İkinci
parametre üç değer alabilir: Eğer kontrole ilişkin ayarlama yapılıyorsa SB_CTL,
pencereye gömülü scroll bar ayarlamaları için SB_VERT ya da SB_HORZ
kullanılmalıdır. Üçünü ve dördüncü parametreleri skala aralığını belirtir.
Beşinci parametre kontrol üzerindeki görüntünün güncellenmesiyle ilgilidir.
Skala belirlendikten sonra WM_HSCROLL ya da WM_VSCROLL mesajları işlenir. Mesaj
içerisinde mesajın geliş sebebi bir switch ile soruşturulmalıdır.
Bu switch içerisinde şu
belirlemeler yapılmalıdır:
- Scroll bar ok'larına click yapıldığında ne kadar bir öteleme yapılacak,
- Ara bölgelere click yapıldığında ne kadar öteleme yapılacak,
Bu belirlemelerden sonra
switch deyiminin dışında SetScrollPos API fonksiyonuyla düğme yeni yerine
yerleştirilmelidir. Prototipi:
Klavye Mesajları
Klavyede bir tuşa
basıldığında WM_KEYDOWN çekildiğinde de WM_KEYUP mesajları Windows tarafından
gönderilir. Klavye mesajları girdi odağına(input focus) sahip olan pencereye
gönderilmektedir. Bir t anında üzerinde mavi bant olan pencereye aktif pencere
denir. Yalnızca hWndParent olarak NULL girilmiş olan pencereler aktif olabilir.
Yani yalnızca top level pencereler aktif olabilir. Mouse ile bir üst pencerenin
içindeki alt pencereye click yapıldığında alt pencerenin en üst penceresi
otomatik olarak aktif pencere yapılır. Girdi odağı(input focus) klavye
mesajlarının gönderileceği penceredir. Girdi odağı bir alt pencereye
verilebilir. Özetle bir üst pencerenin içerisinde bir alt pencere varsa ve alt
pencerenin üzerine click yapılmışsa girdi odağını alan pencere alt pencere olur
ama o pencerenin en üst penceresi aktif pencere yapılır. Girdi odağını herhangi
bir pencereye verebilmek için SetFocus API fonksiyonu kullanılır. Prototipi:
Fonksiyonun parametresi girdi odağının verileceği pencerenin handle'ıdır.
Fonksiyonun geri dönüş değeri girdi odağına sahip olan eski pencerenin
handle'ıdır.
Girdi odağı bir alt
pencereye verilirse o pencerenin en üs penceresi otomatik olarak aktif pencere
olur. Girdi odağının hangi pencerede olduğu GetFocus API fonksiyonuyla
alınabilir. Prototipi:
Fonksiyon girdi odağına sahip olan pencerenin handle'ıyla geri döner.
Sanal Karakter Kodları(Virtual Key Codes)
Klavyedeki özel tuşların
ASCII kodları 0'dır. Bu tuşlar birbirlerinden scan code'larıyla ayrılabilir.
Scan code'ları ise genel olarak donanıma bağlı bir biçimde belirlenmektedir.
Windows sistemlerinde değişik donanıma sahip klavyeler bağlanabilir. Bu
klavyeler üzerindeki özel tuşların scan code'ları birbirlerinden farklı
olabilir. Örneğin 101/102 tuşlu IBM klavyelerinde F1 tuşunun extended scan
code'u 0x3B'dir. Windows sisteminin pek çok değişik donanımlarda çalışabileceği
varsayılmıştır. Eğer özel tuşların scan code'ları doğrudan program içerisinde
kullanılsa önemli bir taşınabilirlik problemi çıkar. Örneğin:
Burada ch ile F1 tuşu karşılaştırılmaya çalışılmıştır. Çünkü F1 tuşunun
extended scan code'u 0x3B'dir. Ancak bu program farklı bir donanımda
çalıştırılmak istendiğinde o donanımdaki F1 tuşunun scan code'u 0x3B
olmayabilir. Bunun çözümü için sanal karakter kodları tasarlanmıştır. Basılan
tuşun bilgisi klavye sürücüsü tarafından standart sanal karakter kodlarına
dönüştürülmektedir. Program içerisinde programcı donanım ne olursa olsun hep
sanal karakter kodlarını kullanır. Çünkü scan code'dan sanal karakter koduna
dönüşüm yapılması aşağı seviyede çalışan klavye sürücüsü tarafından
yapılmaktadır. Windows.h içerisinde VK_XXX biçiminde bütün tuşların sanal
karakter kodları sembolik sabitler biçiminde tanımlanmıştır. Sonuç olarak özel
tuşlar kullanılacaksa onların sanal karakter kodları kullanılmalıdır. Alfabetik
ve sayısal karakterlerin sanal karakter kodları ASCII kodlarıyla aynıdır.
Bunlar için özel bir VK_ tanımlamasına gerek duyulmamıştır.
Klavye Mesajları
Klavyede bir tyuşa
basıldığında WM_KEYDOWN, çekildiğinde ise WM_KEYUP mesajları gönderilir.
Sisteme ilişkin özel tuşlar için ayrıca WM_SYSKEYDOWN ve WM_SYSKEYUP mesajları
gönderilir. Bu mesajalrın parametreleri şöyledir: wParam parametresine basılan
tuşun sanal karakter kodu yerleştirilir. lParam parametresi aşağıdaki gibi
düzenlenmiştir:
Yineleme sayısı normal olarak 1 olur. Sistem çok yavaşladığında bir tuşa
sürekli basılma durumunda iki tuşa basılma arasında anı tuşun bilgisini farklı
bir mesaj biçimin değil, aynı mesajın yinelenme sayısı biçiminde
kodlayabiliyoruz. OEM scan code klavyenin orijinal scan code'udur.
WM_CHAR Mesajı
WM_CHAR mesajı Windows
tarafından kuyruğa gönderilmez. TranslateMessage API fonksiyonu tarafından
çağırılır. Prototip:
Bu fonksiyon isteğe bağlı
olarak mesaj döngüsünün içerisine yerleştirilir. Yani bu fonksiyon mesaj
dögüsünden kaldırılsa WM_CHAR mesajı oluşmaz. Bu fonksiyon kuyruktan alınan
mesajı inceler, bu mesaj WM_KEYDOWN ise basılmış olan tuşun bir ASCII tuşu olup
olmadığına bakar. Eğer basılan tuş bir ASCII tuşu ise bu tuş için WM_CHAR
mesajını kuyruğa yerleştirir. Bu mesajın wParam parametresi basılan tuşun
UNICODE karakter karşılığıdır(ASCII tablosu UNICODE tablosunun ilk 256
karakteridir). lParam WM_KEYDOWN mesajında olduğu gibi ilave bilgileri içerir.
Program içerisinde
görüntülenmek istenen bir yazı söz konusuysa WM_KEYDOWN mesajı yerine WM_CHAR
mesajının işlenmesi daha uygundur.
Listbox kontrolünde enter tuşuna basıldığında sanki doubleclick yapılmış
gibi seçme işleminin sağlanması yukarıdaki gibi bir işlemle sağlanabilir.
Modeless Dialog Pencereleri
Modal bir dialog penceresi DialogBox
API fonksiyonuyla açılır, EndDialog API fonksiyonuyla kapatılır. Modal bir
dialog penceresine girildiğinde dialog penceresinin gerçek pencere fonksiyonu
mesaj kuyruğunu kontrol altına alarak yalnızca dialog işlemlerinin yapılmasını
sağlar. Oysa modeless dialog pencereleri mesaj döngüsünü kontrol altına almaz.
Ayrı bir üst pencere gibi çalışmaktadır. Modeless dialog pencerelerinin
mesajları ana mesaj döngüsü yoluyla işlenir. Modeless bir dialog penceresi
CreateDialog API fonksiyonuyla yaratılır. Bu fonksiyon kaynaktan(resource)
hareketle bütün kontrolleri yaratır ve çalışmasını bitirir. Tabii pencere
görünür durumda kalır. Modeless dialog pencerelerinin mesajları normal bir
pencere gibi ana mesaj döngüsünden hareketle ele alınmaktadır. Kullanıcı
açısından bakıldığında modal ve modeless dialog pencereleri arasında önemli
farklar vardır. Modal dialog penceresi açıldığında dialog penceresi dışında
diğer pencereler için hiçbir işlem yapılamaz(Kapatılana kadar). Oysa modeless
dialog pencereleri açıldığında başka pencerelerle ilgili işlemler gerçekleştirilebilir.
Modeless dialog pencereleri çok nadir kullanılır(Tipik uygulaması Find &
Replace). Modeless dialog pencereleri "Owned Window" olarak
yaratılır. Yani asıl pencerenin dışına sürüklenebilir. Ana pencere minimize
edildiğinde o da minimize edilir. Modeless dialog pencereleri normal bir
pencere gibi DestroyWindow API fonksiyonuyla kapatılır.CreateDialog API
fonksiyonunun prototipi:
Tıpkı modal dialog
pencerelrinde olduğu gibi modeless dialog pencerelerin de bir pencere
fonksiyonları vardır. Kontroller yine gerçek pencere fonksiyonunun WM_CREATE
mesajında oluşturulur. Programcının son parametre olarak belirttiği pencere
fonksiyonu gerçek pencere fonksiyonu değildir, onun tarafından çağırılacak
yapay pencere fonksiyonudur.
Modeless Dialog Penceresine İlişkin Uygulama
Fırtça yaratmak için kullanılan CreateBrushIndirect
fırçanın pek çok özelliğini belirlememize olanak sağlanmaktadır. Bu fonksiyonun
alternatifi olarak CreateSolidBrush fonksiyonu kullanılabilir. Bu fonksiyon
yalnızca fırçanın rengini belirlememize olanak sağlar. Prototipi:
Uygulamanın menü yapısı:
Uygulamada modeless dialog penceresinin içerisindeki
scroll barların ID değerleri bilinçli olarak 10, 11, 12 biçiminde yani ardışıl
olarak verilmiştir. Bunun nedeni dialog penceresine iletilen mesajların kolay
işlenmek istenmesidir.
Bir dialog penceresinin yeniden açıldığında en son
görüntüyü koruması bazen istenebilir. Bunun için kontrol bilgileri çıkarken
global değişkenlere atanır. WM_INITDIALOG mesajında da o değerlerle tekrar
kontroller konumlandırılır.
IsDialogMessage API Fonksiyonu
Modeless dialog pencereleri için ayrıca mesaj döngüsünün
içerisinde IsDialogMessage API fonksiyonunun çağırılması gerekir. Eğer bu
fonksiyon çağırılmazsa modeless dialog penceresi pek çok işlemini yapar ancak
özellikle klavye ile ilgili işlemlerde başarısız olur. Bu fonksiyon mesajın
modeless dialog penceresine ilişkin olup olmadığını tespit eder, eğer ilişkinse
bazı ek işlemlerden sonra kendi içerisinde TranslateMessage ve DispatchMessage
fonksiyonlarına sokar. Eğer kuyruktan alınan mesaj bir modeless dialog
penceresine ilişkinse ayrıca TranslateMessage ve DispatchMessage
fonksiyonlarına sokulmamalıdır. Fonksiyonun geri dönüş değeri 0 ise mesaj
modeless dialog penceresine ilişkin değildir, o halde işlenmelidir. 0 dışı bir
değer ise mesaj modeless dialog penceresine ilişkindir işlenmemelidir.
Genellikle modeless dialog pencerelerinin handle değerleri global değişkenlerde
saklanır. Başlangıçta bu global değişkenin içerisine NULL değeri koymak kontrol
açısından uygundur. özetle bir modeless dialog penceresi açılacaksa programın
mesaj döngüsü şöyle olmalıdır:
SetDlgItemInt ve GetDlgItemInt Fonksiyonları
Bu fonksiyonlar aslında SetDlgItemText ve GetDlgItemText
fonksiyonlarının başka biçimleridir. SetDlgItemInt fonksiyonu bir int sayıyı
parametre olarak alır. Bunu yazısal biçime dönüştürerek SetDlgItemText ile
pencere yazısını değiştirir. GetDlgItemInt fonksiyonu da pencere yazısını
alarak bunu atoi fonksiyonundan geçirir ve bir int sayı biçiminde programcıya
verir. Bu fonksiyonlar özellikle edit ve static kontrollerinde
kullanılmaktadır.
Timer İşlemleri
Eğer programcı isterse belirlenen bir periyodla kuyruğa
WM_TIMER isimli mesaj Windows tarafından gönderilebilir. Bu sayede periyodik
işlem gerektiren durumların üstesinden gelinebilir. Örneğin belirli aralıklarla
bir işlemi yürüten programlar ya da saat programları bu mesajdan faydalanılarak
yazılırlar. Mesajın yollanacağı periyod milisaniye mertebesinde belirlenebilir.
Buradaki periyod uzunluğu sistemin çalışmasına bağlı olarak ileri ve geri yönde
sapmalar gösterebilir. Zamana dayalı kritik işlemler bu mesaj kullanılarak
gerçekleştirilemez. Sistemin WM_TIMER mesajını kuyruğa bırakabilmesi için
SetTimer API fonksiyonuyla bir timer yaratmak gerekir. Prototipi:
);
Fonksiyonun birinci
parametresi mesajın gönderileceği pencerenin handle değeridir. Fonksiyonun
ikinci parametresi yaratılacak timer'ın ID değerdir. Eğer daha önce bu ID
değeriyle bir timer yaratılmışsa eskisi silinerek yenisi geçerli olur. Bu değer
genellikle sembolik sabit olarak tanımlanır. Bir programın birden fazla timer
yaratması durumunda bu ID değeri timer'ların tespit edilmesi amacıyla
kullanılır. Windows bir timer'ın zamanı geldiğinde kuyruğa WM_TIMER mesajını
bırakır ve mesajın wParam parametresine ID değerini yerleştirir. Programcı da
bir switch içerisinde mesajın hangi timer dolayısıyla gönderildiğini anlar. Bu
değer aynı zamanda bir handle değeri gibi kullanılmaktadır. Örneğin timer yok
edilirken bu ID değeri kullanılmaktadır. Fonksiyonun üçünü parametresi
milisaniye cinsinden gönderilme periyodunu belirtir. Fonksiyonun son
parametresi timer fonksiyonunun baişlangıç adresini alır. Bu değer NULL
girilebilir. Bu fonksiyonun aşağıdaki gibi bir parametrik yapıya sahip olması
gerekir:
Fonksiyonun geri dönüş değeri başarı durumunda ikinci
parametresiyle girilen ID değerinin aynısıdır. Başarısızlık durumunda 0'dır.
Fonksiyonun başarısının kontrol edilmesinde fayda vardır.
WM_TIMER Mesajı
Bu mesajın wParam parametresine timer'ın ID değeri, lParam
parametresine ise SetTimer fonksiyonunun son parametresi olarak geçirilen
fonksiyonun adresi yerleştirilir.
Yaratılan timer çalışma bitirilince KillTimer
fonksiyonuyla yok edilir. Prototipi:
Örnek programda timer WM_CREATE mesajında yaratılmış,
WM_DESTROY mesajında da yok edilmiştir.
SetTimer fonksiyonun son parametresi NULL yerine
belirtilen parametre yapısına sahip bir fonksiyonun başlangıç adresi olarak
girilirse periyod dolduğunda doğrudan o fonksiyon çağırılır.Bu durumda WM_TIMER
mesajı etkisiz kalır. Aslında bu durumda mesaj yine kuyruğa bırakılır, ancak
DispatchMessage API fonksiyonu pencere fonksiyonunu çağırmak yerine bu
fonksiyonu çağırır.
SetTimer fonksiyonunun birinci parametresi de NULL
girilebilir. Bu durumda son parametre mutlaka girilmelidir. DispatchMmessage
API fonksiyonu belirtilen fonksiyonu çağırır.
Bir BMP Çizimi Yapmanın Adımları
1. Bitmap resource'ta
çizilir, ya da FindResource fonksiyonuyla doğrudan dosyadan yüklenir.
LoadBitmap fonksiyonuyla bitmap'e ilişkin handle elde edilir.
2. WM_PAINT içerisinde
CreateCompatibleDC ile bellek için DC elde edilir ve SelectObject fonksiyonuyla
bu DC için bitmap seçilir.
3. BitBlt fonksiyonuyla
bellek tabalı DC'den normal DC'ye kopyalama yapılır.