Standart Dialog Pencereleri
işletim |
Her Windows programında
gördüğümüz Open, Save, Find-Replace, Color, Font, Print gibi dialog pencereleri
tek bir API fonksiyonuyla oluşturulabilen standart dialog pencereleridir.
Open ve Save Dialog Pencereleri
Open ve Save dialog
pencereleri hemen hemen birbirlerinin aynısıdır. Open penceresi dosya açmak,
Save penceresi saklamak amacıyla kullanılır. Open dialog penceresi
GetOpenFileName API fonksiypnuyla, Save dialog penceresi ise GetSaveFileName
API fonksiyonuyla yaratılır. Bu dialog pencereleri ilgili API fonksiyonlarıyla
yaratıldıktan sonra kullanıcı bir dosya seçerek OK tuşuna basar(Dosya ismi
klavyeyle de yazılabilir). Böylece fonksiyon sonlanır. Programcı seçilen
dosyanın ismini elde eder. Bu iki API fonksiyonu da OPENFILENAME isimli bir
yapı değişkeninin adresini alır. OPENFILENAME yapısının elemanları genel olarak
ikisi dışında bu dialog penceresini konfigüre etmek amacıyla kullanılır. Ancak
iki eleman bu API fonksiyonları tarafından doldurulur. Seçilmiş dosyanın isim
ve path ifadesi bu iki elemana yazılır. Bu API fonksiyonlarının geri dönüş
değerleri FALSE ise kullanıcı dialog penceresini cancel ile kapatmıştır, TRUE
ise ok ile kapatmıştır. OPENFILENAME yapısının lpstrFilter elamanı Open ve Save
pencerelerinde çıkan filtreleme bilgilerini barındırır. Her filtre elemanı iki
parçadan oluşur. Birinci parça yazı parçasıdır, ikinci parça filtreleme
bilgisini tutar.
Pencere Başlık Yazısının Değiştirilmesi
Pencere başlığı üzerinde
işlem yapan iki fonksiyon vardır: GetWindowText ve SetWindowText. SetWindowText
fonksiyonu CreateWindow fonksiyonunun ikinci parametresiyle belirtilen pencere
başlığı yazısının değiştirilmesini sağlar.
BOOL
SetWindowText(HWND hWnd, LPCSTR lpString);
Bu fonksiyon pushbutton penceresine uygulanırsa düğme üzerindeki yazının
değiştirilmesine, editbox penceresine uygulanırsa editbox içerisindeki yazının
değiştirilmesine, static penceresine uygulanırsa static pencere yazısının
değiştirilmesine yol açar.
GetWindowText fonksiyonu
bunun tam tersi olarak pencere başlık yazısının elde edilmesinde kullanılır.
BOOL
GetWindowText(HWND hWnd, LPSTR lpString, int nMaxCount);
Bu fonksiyonlara ek olarak
üst pencerenin handle değeri ve alt pencerenin ID değerleri bilindiğinde alt
pencerenin pencere başlığı üzerinde işlem yapan SetDlgItemText ve
GetDlgItemText fonksiyonları da vardır. Tabii bu fonksiyonlar kendi içlerinde
GetDlgItem ve SetWindowText, GetWindowText fonksiylarını kullanarak işlem yaparlar.
OPENFILENAME Yapısının Önemli Elemanları
Bu yapının ilk elemanı
olan lStructSize elemanı yapının byte uzunluğunu tutmalıdır. hwndOwner elemanı
standart dialog penceresini açan üst pencerenin handle değerini tutar.
hInstance elemanına programın hInstance değeri girilmelidir. Bu yapının en
önemli elemanlarından birisi lpstrFilter elemanıdır. Bu eleman birden fazla
yazıyı tutan bir gösterici biçimindedir. C'de char türünden bir göstericinin
birden fazla yazıyı tutabilmesi şöyle mümkün olabilir: Her yazının sonu NULL
karakter ile bitirilir, tüm yazının bittiği ise iki NULL karakter kullanılarak
anlatılır. lpstrFilter elemanı filtre yazılarını tutar. Her filtre elemanı iki
yazıdan oluşmaktadır. Bu yazının ilki filtreleme sırasında çıkacak yazıyı belirtit
ve filtreleme üzerinde bir etkisi yoktur. İkinci yazı filtrelemeye ilişkin
yazıdır. Birden fazla filtreleme için ; koymak gerekir. Örnek:
x.lpstrFilter = "Executable Files\0*.exe;*.com\0Text
Files\*.txt\0";
Seçim yapıldıktan sonra elde edilen dosya ismi bu API fonksiyonları
tarafından lpstrFileTitle elemanının gösterdiği adrese yerleştirilir. Yani
fonksiyon çağırılmadan önce bu elemanın tahsis edilmiş bir diziyi göstermesi
gerekir. nMaxFileTitle elemanı ise bu dizinin en büyük uzunluğunu belirtmektedir.
Bu eleman dosya ismini path ifadesi olmadan yalnızca isim biçiminde tutar.
Tabii dosyanın uzantısı da alınmaktadır. Yapının lpstrInitialDir elemanı dialog
penceresinin default hangi dizin için açılacağını belirtir. Seçilen dosyanın
ismi tüm path bilgisiyle birlikte lpstrFile elemanının gösterdiği adrese
yerleştirilir. Bu elemanın gösterdiği yazının maksimum elemanın nMaxFile
elemanında saklanmalıdır.
Örnek Programın Açıklaması
Örnek programda bir menü
alınmış, menüye Open, Save ve Exit elemanları yerleştirilmiştir. Sembolik
sabitleri ID_FILE_OPENX, ID_FILE_SAVEX, ID_FILE_EXITX.
Checkbox ve Radiobutton Kontrolleri
Checkbox küçük bir kare ve
yanında yazı bulunan bitr konroldür. Genellikle dialog pencerelerinin
içerisinde kullanılır. Üzerine click yapıldığında içi çarpılanır. Genellikle
bir özelliği dahil etmek ya da kaldırmak amacıyla kullanılır. Bu kontrolden
elde edilecek bilgi kontrolün çarpılanıp çarpılanmadığıdır. Checkbox kontrolü
CreateWindow fonksiyonunda "button" sınıf ismi girilerek yaratılır.
Ancak pencere biçimi olarak BS_CHECKBOX girilir.
hCheckBox =
CreateWindow("button", "Example", WS_CHILD | WS_VISIBLE |
BS_CHEKBOX.....);
CreateWindow fonksiyonunun ikinci parametresinde belirtilen pencere başlık
yazısı kare görüntüsünün yanında çıkar. Checkbox'lar otomatik, normal ve üç
konumlu omlak üzere üçe ayrılırlar. Checkbox kontrolüne çarpı koyabilmek için
BM_SETCHECK mesajı gönderilir. Bu mesajda lParam 0 alınır, wParam 1 ya da 0
olabilir. 1 çarpılama oluşacağını, 0 oluşmayacağını belirtir.
SendMessage(hCheckBox,
BM_SETCHECKBOX, 1, 0);
Checkbox kontrolünün çarpılanıp çarpılanmadığını BM_GETCHECK mesajı ile
elde edebiliriz. Bu mesajda wParam ve lParam 0 girilir. Fonksiyonun geri dönüş
değeri 0 ya da 1 olur. 1 çarpılı, 0 çarpısız anlamına gelir.
status =
SendMessage(jhCheckBox, BM_GETCHECK, 0, 0);
Checkbox kontrolü üzerine click yapıldığında tıpkı pushbutton kontrolünde
olduğu gibi checkbox kontrolü WM_COMMAND mesajı ile BN_CLICKED durum kodu ile
çağırılır. Normal checkbox'larda kontrolün üzerine click yapıldığında çarpılama
işlemi kontrolün kendisi tarafından değil, gönderilen mesaj ile programcı
tarafından yapılır. Normal checkbox'larda çarpılama işlemi aşağıdaki gibi
yapılabilir.
case WM_COMMAND:
switch(LOWORD(wPAram)) {
case ID_CHECK:
if
(HIWORD(wParam) == BN_CLICKED) {
if
(SendMessage(hCheckBox, BM_GETCHECK, 0, 0))
SendMessage(hCheckBox,
BM_SETCHECK, 0, 0);
else
SendMessage(hCheckBox,
BM_SETCHECK, 1, 0);
}
break;
}
Oysa otomatik checkbox kontrolünde çarpılama işlemi kontrolünden kendisi
tarafından zaten yapılmaktadır. Otomatik checkbox yaratabilmek için BS_CHECKBOX
yerine BS_AUTOCHECKBOX pencere biçimi kullanılır. Checkbox genellikle dialog
pencerelerinde kullanılır. Dialog penceresi ilk görüntülendiğinde çarpılanmış
bir görüntü elde edebilmek için WM_INITDIALOG mesajında çarpılama işleminin
bilinçli bir şekilde yapılması gerekir.
case WM_INITDIALOG:
SendDlgItemMessage(hWnd,
ID_CHECK, BM_SETCHECK, 1, 0);
return TRUE;
Üç konumlu checkbox kontrolünde checkbox'ın 3 durumu vardır: Çarpılı,
çarpısız ve etkin omayan durum. Bu chackbox kontrolü pencere biçimine ek olarak
BS_3STATE eklenerek yaratılırlar. Otomatik ve üç konumlu chackbox kontrolleri
Win32 sistemleriyle eklenmiştir.
Radiobutton
kontrolü dairesel bir şeklin içerisine noktasal bir şeklin yerleştirilmesine
olanak sağlar. Genellikle bir grup radiobutton kontrolü biçiminde kullanılır.
Genellikle radiobutton kontrollerinin bir anda yalnızca bir tanesi seçili
olacak biçimde kullanılır. Uygulamada birden fazla seçenekten yalnızca bir
tanesinin seçilmesi gerektiği durumlarda kullanılır. Checkbox kontrolleri tek
başlarına kullanılabilir, ancak radiobutton kontrolleri grup olarak
kullanılmalıdır. Bu kontrolün yanında tıpkı checkbox'ta olduğu gibi betimleyici
bir yazı vardır. Bir grup içerisindeki bütün radiobutton kontrolleri tek tek
CreateWindow fonksiyonuyla yaratılmalıdır. Radiobutton kontrolleri normal ve
otomatik olmak üzere iki kısma ayrılırlar. Otomatik radiobutton kontrolleri
Win32 sistemleriyle tanımlanmıştır. Bu kontrolü yaratabilmek için CreateWindow
fonksiyonu içerisinde sınıf ismi olarak "button" girmek, pencere
biçimi olarak BS_RADIOBUTTON ya da BS_AUTORADIOBUTTON vermek gerekir. Pencere
başlık yazısı betimleyici yazı olarak görünür. Bu kontrol ana pencerenin
içerisine gömülmek yerine genellikle dialog pencerelerinde kullanılır.
Radiobutton kontrolünün üzerine click yapıldığında kontrol üst pencereye
BN_CLICKED durum koduyla mesaj gönderir. Radiobutton kontrolünü çarpılamak için
checkbox'ta yapıldığı gibi BM_SETCHECK mesajı gönderilir.
SendMessage(hRadioButton,
BM_SETCHECK, 1, 0);
Bu kontrolün çarpılanıp çarpılanmadığı BM_GETCHECK mesajı ile
sorgulanabilir.
status =
SendMessage(hRadioButton, BM_GETCHECK, 0, 0);
Normal radiobutton'larda bir grup kontrolden bir tanesine click
yapıldığında click yapılanı çarpılamak, çarpılı olanı silmek programcının
görevidir. Autoradiobutton yalnızca dialog pencerelerinde kullanılır. Bunun
için bir radiobutton grubu tanımlanması gerekir. Bu grup kaynak içerisinde
tanımlanabilmektedir. Autoradiobutton grubunda bir kontrole click yapıldığında
click yapılan otomatik olarak çarpılanır. Çarpılanmış olan da otomatik olarak
silinir. Normal radiobutton'larda çarpılama işlemi birkaç biçimde yapılabilir:
case WM_COMMAND:
switch(LOWORD(wParam)) {
case ID_RADIO1:
......
......
......
case ID_RADIO2:
......
......
......
case ID_RADIO3:
......
......
......
}
break;
yada
daha sistematik bir yöntem kullanılabilir:
struct CBOX {
WORD id;
int status;
} x[4] =
{{ID_RADIO1, 0}, {ID_RADIO2, 1}, {ID_RADIO3, 0}, {ID_RADIO4, 0}};
switch
(LOWORD(wParam)) {
case ID_RADIO1:
case ID_RADIO2:
case ID_RADIO3:
case ID_RADIO4:
ProcessCheck(LOWORD(wParam));
break;
}
void
ProcessCheck(WORD id)
{
int i;
HWND hRadio;
for (i = 0; i < 4; ++i) {
if(x[i].status ==
1) {
x[i].status
= 0;
hRadio
= GetDlgItem(hWnd, x[i].id);
SendMessage(hRadio,
BM_SETCHECK, 0, 0);
}
if (x[i].id ==
id) {
x[i].status
= 1;
hRadio
= GetDlgItem(hWnd, id);
SendMessage(hRadio,
BM_SETCHECK, 1, 0);
}
}
}
Örnek programda iki
radiobutton dialogh penceresi üzerine çıkartılmış ve durumları elde edilmiştir.
İster auto, ister normal olsun bir grup içerisindeki hangi radiobutton'ın
çarpılanmış olduğunu anlamak için bir sorgulama yapılması gerekir. En pratik
yöntem hepsine BM_GETCHECK mesajı göndermek ve hangisi çarpılanmışsa onu tespit
etmek olabilir.
Autoradiobutton'larda
radiobutton grubunun tespit edilmesi WS_GROUP pencere biçimiyle yapılmaktadır. Dialog
kaynağında radiobutton kontrolü RADIOBUTTON ismiyle yaratılır. Kaynakta ilk
WS_GROUP pencere biçimine sahip radiobutton grubun ilk elemanı kabul edilir.
Bundan sonraki radiobutton kontrolleri grup içerisindedir. Bir sonraki WS_GROUP
pencere biçimli radiobutton kontrolüne kadarki tüm radiobutton kontrolleri bu
grup içinde kabul edilir.
Çizim İşlemleri
Bir pencerenin üzerine
doığrudan yazısal ya da grafiksel çizimler yapılabilir. Pencerenin üzerine yazı
yazma işlemi de bir çeşit çizim işlemi olarak değerlendirilir. Aslında static
kontrolünü kullanarak yazı yazılması durumunda da bir çeşit çizim işlemi
yapılmaktadır. Ancak burada çizim işlemini static kontrolünün pencere
fonksiyonu yapar. Oysa bir yazı yazmak için bir alt pencerenin tanımlanması gerekmez.
Bir pencere içerisinde yapılan çizim Windows tarafından otomatik olarak
saklanmaz. Örneğin bir pencere başka bir pencere tarafından kapatıldığında
Windows kapatılan pencere içerisindeki çizim görüntüsünü saklamaz. Bu
görüntünün, yani bütün pencere çizimlerinin yeniden programcı tarafından
yapılması gerekir. Windows bir pencerenin bir bölümü herhangi bir biçiminde
kapatıldığında ya da açıldığında o pencere için mesaj kuyruğuna WM_PAINT
mesajını bırakır. Bu durumda pencere içerisindeki bütün mesajlar WM_PAINT
mesajı içerisinde yapılmalıdır. WM_PAINT mesajı şu durumlarda gönderilir:
1. Pencerenin boyutları değiştirildiğinde,
2. Bir pencereyi kaplamış olan başka bir pencerenin çekilmesi durumunda,
WM_PAINT şu durumlarda gönderilmez:
1. Bir menünün açılmasıyla ve kapatılmasıyla oluşan durumda Windows pencere
görüntüsünü otomatik olarak saklar, WM_PAINT mesajını göndermez.
2. Bir pencere taşındığında Windows pencere görüntüsünü otomatik olarak
oluşturur.
Pencere Çizimleri Nerede Yapılamalıdır?
Windows pencere çizim
görüntülerini otomatik olarak saklamadığı için pencere görüntüsünün her
değişiminde yani her WM_PAINT mesajı geldiğinde bütün çizimler yeniden
yapılmalıdır. Bu durumda bütün çizimler WM_PAINT mesajı içerisinde
yapılmalıdır. Eğer çizimler başka yerde yapılırsa pencere görüntüsünün
değişiminde başka yerde yapılan çizimler kaybolur.
Pencere Güncelleme Alanı(Window Update Region)
Bir pencerenin yeniden
çizilmesi gereken en küçük dikdörtgensel alanına güncelleme alanı denir.
Güncelleme alanı dikdörtgensel olmak zorundadır. Pencere
içerisindeki görüntüyü yeniden oluşturmak için yalnızca güncelleme alanı
içerisindeki bölümün yeniden çizilmesi yeterlidir. Üçgensel bir bölge ya da
dairesel bir bölge güncelleme alanı olamaz. Windows bu bölgelere ilişkin en
küçük dikdörtgeni hesap ederek güncelleme alanı yapar. Windows her pencere için
bir günceleme alanının koordinat bilgisini tutmaktadır. Tabii Windows her
pencere için tek pencere alanı tutar ve bunu sürekli güncelleştirir. Örneğin
bir pencerenin boyutu değiştirildiğinde güncelleme alanı tüm pencere olur. Bir
pencerenin güncelleme alanının koordinat bilgisi bir API fonksiyonu yardımıyla
sistemden alınabilir. Güncelleme alanı boş küme ise pencerenin hiçbir bölgesinin yeniden
çizilmesine gerek yoktur. Güncelleme alanının boş küme yapılması Windows
tarafından otomatik bir biçimde yapılmaz. Windows güncelleme alanını
gerektiğinde güncelleştirir. Örneğin daraltp genişletebilir. Ancak boş küme
yapmaz. Windows bütün pencerelerin güncelleme alanlarına periyodik olarak
bakar, güncelleme alanı boş küme olmayan bir pencere alanıyla karşılaştığında
ona WM_PAINT mesajını gönderir. Bu mesajı göndermesiyle kendisi güncelleme
alanını ototatik olarak boş küme yapmaz. Güncelleme alanı programcı tarafından
boş küme yapılmalıdır. Güncelleme alanının boş küme yapılması için en iyi yer
WM_PAINT mesajının içidir. Yani sonuç olarak eğer WM_PAINT içerisinde
güncelleme alanı boş küme yapılmazsa pencereye sürekli WM_PAINT mesajı
gönderilir, program da sürekli ,çiizm yapan bir biçimde çalışır ve performans
kaybı olur(Aslında Windows yeni güncelleme alanı eski güncelleme alanının
içerisinde kalıyorsa güncelleme alanını güncellemez).
0 yorum: