Push button Kontrolü
| işletim |
Bu kontrol bir işlemi
başlatmak ya da iptal etmek gibi amaçlarla kullanılır. Bu kontrole yapılan en
önemli hareket tek click işlemidir. Kontrole tek click yapıldığında görüntüsel
olarak basma ve çekme hareketi elde edilir. Her ne
kadar pushbutton kontrolü üzerine çift click işlemi tanımlanmış olsa da
uygulamada kullanılması tavsiye edilmemektedir. Tuş görüntüsünün basılmış
olması ya da çekilmiş olması görüntüsü programlama yoluyla ayrı ayrı elde
edilebilir. Ancak basılmış durumda kalmış olan bir tuş görüntüsü tercih
edilmemektedir.
Pushbutton
kontrolünü yaratabilmek için sınıf ismi olarak "button" girilir. Ancak
button sınıfı diğer bazı kontroller için de kullanıldığından yaratılan
kontrolün bir pushbutton olup olmadığı CreateWindow fonksiyonunun pencere
biçimi parametresiyle verilir. CreateWindow fonksiyonunun pencere başlığı
yazısı tuş görüntüsünün üzerinde yer alır. Button sınıfı için özel pencere
biçimleri şunlardır:
|
BS_PUSHBUTTON
|
Bu pencere biçimi pushbutton kontrolü için zorunlu
olarak kullanılır.
|
|
BS_DEFPUSHBUTTON
|
Eğer bir grup pushbutton kontrolü arasında klavye
odağı(input focus) bu pushbutton kontrollerinin hiçbirinde değilse enter
tuşuna basıldığında DEFBUSHBUTTON ile belirtilen pushbutton kontrolüne click
yapılmış varsayılır.
|
Pushbutton Kontrolünün Üst Pencereye
Gönderdiği Mesajlar
(Pushbutton Notification Messages)
Pushbutton
kontrolü mouse ile kontrolün üzerine click yapıldığında SendMessage
fonksiyonuyla üst pencerenin pencere fonksiyonunu WM_COMMAND mesajıyla çağırır.
Bunun dışında tavsiye edilmemesine karşın çift click işleminde de bu kontrol
üst pencerenin pencere fonksiyonunu aynı biçimde çağırmaktadır.
WM_COMMAND Mesajı
WM_COMMAND
mesajı iki durumda çağırılmaktadır.
1. Menüden bir eleman seçildiğinde lParam 0,
HIWORD(wParam) 0 ve LOWORD(wParam) menü elemanının ID değeri olur.
2. Bu mesaj Windows sisteminin standart kontrollerinde bir
olay gerçekleştiğinde üst pencereyi haberdar etmek için de kullanılır. Bu
durumda lParam alt pencerenin handle değerine, HIWORD(wParam) mesajın ne
sebeple gönderildiğine ait koda(notification code), LOWORD(wParam) alt
pencerenin ID değerine sahip olur. Bu durumda alt pencerede bir olay
gerçekleştiğinde bu olayın nedenini anlayarak uygun kodları çalıştırmak için
WM_COMMAND mesajı işlenmelidir.
WM_COMMAND
mesajı içerisinde HIWORD(wParam) ve LOWORD(wParam) değerlerine istenilen bir
sırada bakılmalıdır. LOWORD(wParam) değerinin kontrol edilmesiyle mesajın hangi
kontrolden geldiği tespit edilebilir. HIWORD(wParam)'a bakılarak da mesajın
hangi nedenle geldiği tespit edilir.
Çok
fazla kontrol için WM_COMMAND mesajının işlenmesi programlama açısından zordur.
Bunun için WM_COMMAND mesajının işlenmesi daha sistematik bir biçimde
yapılabilir. Örneğin iç içe switch'ler kullanılabilir.
case
WM_COMMAND:
switch(LOWORD(wParam)) {
case ID1:
switch(HIWORD(wParam)
{
.......
.......
.......
}
case ID2:
switch(HIWORD(wParam)
{
.......
.......
.......
}
.......
.......
}
break;
Ancak iç içe switch'ler yerine fonksiyon çağırmalarıyla daha okunabilir bir
yapı da elde edilebilir.
case
WM_COMMAND:
switch(LOWORD(wParam)) {
case ID1:
HandleCtrl1(HIWORD(wParam);
break;
case ID2:
HandleCtrl2(HIWORD(wParam);
break;
.......
.......
}
break;
Bu örnekte programcı her kontrol için bir fonksiyon tanımlamıştır.
Fonksiyonların parametresi kontrol üzerinde gerçekleştirilen eyleme ilişkindir.
Menüden bir elemanın
seçilmesi sırasında ve bir kontrol üzerinde bir eylemin gerçekleştirilmesi
durumunda her ikisi için de WM_COMMAND mesajı çağırıldığına göre bu durum bir
karışıklığa yol açabilir. Eğer menü elemanının ID değeriyle kontrolün ID değeri
aynı alınırsa mesajın ne sebepten geldiği anlaşılamayabilir. Bunun için en
pratik çözüm bu ID değerlerinin farklı alınmasıdır. Eğer farklı alınmazsa bu
kontrol WM_COMMAND mesajı içerisinde ayrıca yapılamlıdır.
case WM_COMMAND:
if (lParam) {
....../*Kontrol
mesajı*/
}
else {
....../*Menü
mesajı*/
}
WM_COMMAND mesajı işlendiğinde pencere fonksiyonu 0 değeriyle geri
dönmelidir.
Pushbutton Kontrolünün Üst Pencereye Gönderdiği Mesajların İşlenmesi
Eğer HIWORD(wParam) aşağıdaki
değerlerden bir tanesi ise ilgili olaylar gerçekleşmiştir:
|
BN_DBLCLK
|
Çift click yapılmıştır.
|
|
BN_CLICKED
|
Tek click yapılmıştır.
|
Üst Pencerenin Pushbutton Kontrolüne Gönderdiği Mesajlar
Pushbutton kontrolünün
çeşitli görüntüsel ve işlevsel işlemleri yapabilmesi için üst pencere kontrole
mesaj gönderebilir. Bu mesajlar şunlardır:
BM_CLICK Eğer bu mesaj pushbutton
kontrolüne gönderilirse sanki mouse ile tek click yapılmış gibi bir işleme yol
açar. Bu durumda pushbutton kontrolü yine WM_COMMAND ile üst pencerenin pencere
fonksiyonunu çağıracaktır. Bu mesajın wParam ve lParam parametreleri 0
girilmelidir.
BM_SETSTATE Mesajı
Bu mesajla lParam
parametresine 0 verilir, wParam ya 0 ya 1 olur.Eğer 1 verilirse basılma
görüntüsü 0 verilirse çekilme görüntüsü oluşur. Yalnız bu durum sadece görüntü
üzerinde etkili olur. Pushbutton bu mesajı alınca üst pencereye BN_CLICK
bilgisi göndermez.
BM_GETSTATE Mesajı
Bu mesajla wParam ve
lParam 0 olarak girilir. Bu mesaj gönderildiğinde SendMessage fonksiyonunun geri
dönüş değeri pushbutton kontrolünün durumu hakkında bilgi verir.
Edit Kontrolü
Bu kontrol bir yazının
klavyeden girilerek elde edilmesi için kullanılır. Edit kontrolünü yaratabilmek
için CreateWindow fonksiyonunda sınıf ismi "edit" olarak girilmelidir.
Edit kontrolü tek satırlı veya çok satırlı olabilir. Pencere başlığı olarak
belirlenen yazı edit alanının içine başlangıçta yazılır. Edit kontrolü bir
editörün yapabileceği her türlü işlemi gerçekleştirebilen bir kontroldür.
Örneğin kendi içerisinde bütün özel tuşlara duyarlıdır, undo özelliği vardır,
clipboard özelliği vardır.
Edit Kontrolünün Özel Pencere Biçimleri
Edit kontrolünü yaratırken
WS_ biçimindeki genel pencere biçimlerine ek olarak ES_ ile başlayan çeşitli
pencere biçimleri de kullanılabilir.
|
ES_LEFT, ES_RIGHT, ES_CENTER
|
Kontrol içerisindeki yazısın hizalanmasını sağlamak için kullanılırlar.
|
|
ES_UPPPERCASE, ES_LOWERCASE
|
Kontrol içerisine yazılanların tamamını büyük/küçük harf olacak şekilde
yazılmasını sağlamak için kullanılır.
|
|
ES_READONLY
|
Klavye kullanılarak kontrol içerisine birşey yazılamaz.
|
|
ES_PASSWORD
|
Yazılanların görüntülenmemesini sağlayarak geri almakta kullanılır.
|
|
ES_AUTOHSCROL, ES_AUTOVSCROLL
|
Yatay ve dikey scroll işlemlerine olanak sağlar.
|
|
ES_MULTILINE
|
Eğer bu pencere biçimi kullanılmazsa default olarak edit kontrolü tek
satırlı olur.
|
Üst Pencerenin Edit Kontrolüne Gönderdiği Mesajlar
1. Edit kontrolündeki yazının elde edilmesi
Bu işlem
için edit kontrolüne EM_GETLINE mesajı gönderilir. Bu mesajın wParam parametresi
0 olaral girilmelidir. Bu mesajı alan edit kontrolü yazıyı lParam
parametresiyle belirtilen adrese kopyalar. Ancak sonuna NULL karakter eklemez,
NULL karakterin programcı tarafındanh eklenmesi gerekir. Bu mesaj
gönderildiğinde SendMessage fonksiyonu kopyalama yaptığı yazının karakter
uzunluğuyla geri döner. Ancak kullanıcı edit kontrolüne çok fazla bilgi girmiş
olabilir. Bu durumda bilginin kopyalanacağı karakter dizisinin uzunluğu ne
olacaktır? Kuşkusuz en iyi çözüm başka bir mesajla önce satırdaki karakter
sayısını almak, sonra dinamik bir dizi tahsis ederek tüm bilgiyi çekmek
olabilir. Ancak bu işlemin program yükü fazladır. Bir gösterici hatasına yol
açmamak için edit kontrolüne kopyalanacak maksimum karakter sayısı
belirtilebilir. Bunun için EM_GETLINE mesajını göndermeden önce kopyalanacak
maksimum karakter sayısını belirtmek için kopyalanacak karakter dizisinin ilk
iki byte'ına WORD formunda bir sayı girmek gerekir. Bu durumda bir edit
kontrolündeki bilginin elde edilmesi için şu kalıp kullanılabilir.
#define SIZE 100
char buf[SIZE];
*(WORD *)buf = SIZE
- 1;
n =
SendMessage(hEdit, EM_GETLINE, 0, (LPARAM)buf);
buf[n] = '\0';
2. Çok Satırlı Edit Kontrolünde Toplam Satır Sayısının Elde Edilmesi
EM_GETLINECOUNT mesajı
wParam 0, lParam 0 parametreleriyle çağırılır. SendMessage fonksiyonunun geri
dönüş değeri olarak toplam satır sayısı olarak alınır.
n =
SendMEssage(hEdit, EM_GETLINECOUNT, 0, 0L);
3. Bir Satırdaki karakter Sayısının Elde Edilmesi
İlk satırın sıra numarası
0 olmak üzere edit kontrolü satırlar biçiminde organize edilmiştir. Bir
satırdaki karakter sayısının elde edilmesi iki işlemle gerçekleşir:
a. Karakter sayısı bulunacak satırın ilk karakterinin index numarasının
buluınması. Edit kontrolü içerisindeki her karakterin bir index numarası
vardır. Kontrol içeridindeki ilk karakterin index numarası 0 olmak üzere, her
karakterin index numarası artan bir sıraya sahiptir. Bunun için EM_LINEINDEX
mesajı kullanılır. Mesaj parametreleri:
wParam = satır no
lParam = kullanılmıyor(0)
Fonksiyonun geri dönüş değeri ilgili satırın ilk karakterinin index
numarasıdır. Eğer satır numarası olarak -1 verilirse edit imlecinin bulunduğu
satırın ilk karakterinin index numarası elde edilir.
b. Karakter sayısı bulunacak satırın ilk karakterinin index numarası elde
edildikten sonra EM_LINELENGTH mesajıyla satırın karakter sayısı elde edilir.
mesaj parametreleri:
wParam = index no
lParam = kullanılmıyor(0)
Eğer index numarası olarak -1 girliirse o zaman seçim yapılmış olan
satırdaki seçilmemiş eleman sayısına geri döner. Eğer seçim yapılmamışsa
imlecin bulunduğu satırdaki toplam karakter sayısına geri döner.
O halde n'inci satırdaki
karakter uzunluğunu elde edilmesi için şunlar yapılmalıdır:
{
int index, numberOfChar;
index = SendMessage(hEdit,
EM_LINEINDEX, n, 0);
numberOfChar =
SendMessage(hEdit, EM_LINELENGTH, index, 0);
}
4.
Pencerenin çalışma alanını tamamen kaplayacak bir edit kontrolünün
oluşturulması.
Bunun için önce edit
kontrolü CreateWindow ile yaratılır, yaratıldıktan hemen sonra WM_SIZE mesajı
geleceğine göre koordinat bilgisi olarak (0, 0, 0, 0) girilebilir. Bundan sonra
WM_SIZE mesajı ile MoveWindow fonksiyonu kullanılarak boyutlandırma tekrardan
yapılır.
WM_SIZE:
MoveWindow(hEdit, 0, 0,
LOWORD(lParam), HIWORD(lParam), TRUE);
break;
5.
Edit kontrolünün içeriğinin değişip değişmediğinin tespit edilmesi.
Özellikle edit
kontrolündeki bilginin saklanacağı zaman böyle bir bilgiye gereksinim duyulur.
Bunun çin EM_GETMODIFY mesajı kullanılır. Mesajın parametreleri:
wParam = 0
lParam = 0
Fonksiyonun geri dönüş değeri 0 ise değişiklik yok, sıfır dışı herahngi bir
değerse deişiklik var anlamına gelir.
6. Edit kontrolünün scroll yapılması.
Bunun için EM_SCROLL
mesajı kullanılır. Bu mesaj ile edit kontrolü düşey olarak scroll yaptırılır.
Mesajın parametreleri:
wParam = scroll sayısı
lParam = kullanılmıyor(0)
Bu scroll değerleri:
SB_LINEDOWN
SB_LINEUP
SB_PAGEDOWN
SB_PAGEUP
biçiminde olabilir.
7. Edit kontrolüne undo işleminin yaptırılması.
Bunun için EM_UNDO mesajı
kullanılır. Mesajın parametreleri:
wParam = 0
lParam = 0
8. Diğer işlemler.
EM_GETSEL mesajı ile
seçilmiş olan karakterlerin index numaraları alınabilir. EM_LINEFROMCHAR ile
karakter index verilen bir karakterin hangi satırda olduğu bilgisini elde
etmekte kullanılır. EM_REPLACESEL seçili olan alan yerine belirlenen bir yazıyı
yerleştirir. EM_GETPASSWORDCHAR ve EM_SETPASSWORDCHAR ile password karakteri
olarak çıkacak karakter get ve set edilir. EM_SETTABSTOP ile tab stop'ların
yerleri belirlenir. EM_SETREADONLY ile edit kontrolü programın belirli bir
aşamasından sonra read-only yapılabilir.
Edit Kontrolünün Üst Pencereye Gönderdiği Mesajlar
1. EN_CHANGE ve EN_UPDATE Mesajları
Bu iki mesaj edit
kontrolüne bir karakter girildiğinde üst pencereye gönderilir. Tabii WM_COMMAND
mesajı içerisinde HIWORD(wParam) EN_CHANGE ya da EN_UPDATE olacak biçimde
gönderilir. Bir tuşa basıldığında karakter görüntülenmeden evvel EN_UPDATE
mesajı bir üst pencereye gönderilir. Yani EN_UPDATE mesajı geldiğinde bir tuşa
basılmıştır ama henüz görüntülenmemiştir. EN_CHANGE ise görüntülenmeden sonra
üst pencereye gönderilir. Yani bir tuşa basıldığında önce EN_UPDATE sonra
EN_CHANGE mesajları üst pencereye gönderilir.
2. EN_HSCROLL ve EN_VSCROLL
Edit kontrolünde yatay ya
da düşey scroll işlemi oluştuğunda bu mesajlar gönderilir.
Edit kontrolü bir takım
gereksinimleri karşılayacak biçimde özellikle EN_CHANGE ve EN_UPDATE mesajları
kullanılarak değişik bir biçimde düzenlenebilir. Örneğin sayısal karakter
dışında bir karakterin basılması engellenebilir. ancak bu kontrol her türlü
bilgi giriş biçimlerini destekleyecek biçimde tasarlanmamıştır. Böylesi bir
durumda edit kontrolüne benzer başka bir kontrol tasarlamak gerekir.
List Box Kontrolü
Bu
kontrol belirli bilgilerin satırlar halinde listelenmesi için kullanılır.
Örneğin 100 kişinin isim ve soyadları ekranda gösterilecekse list box
içerisinde satırlar halinde gösterilebilir. List box satırlardan oluşur. List
box kontrolüne yeni bir satırın eklenmesi ya da bir satırın silinmesi gibi
işlemler kontrole mesjalar gönderilerek yapılır. List box kontrolünde aktif bir
satır söz konusudur. Aktif satır ok tuşlarıyla ya da tek click işlemiyle
değiştirilebilir. Bu kontrol üzerinde en sık yapılan hareket mouse ile belirli
bir satıra double-click işlemidir. Geleneksel olarak böyle bir işlemden sonra
double-click yapılan satıra ilişkin özel işlemler yapılır. List box kontrolü
yatay ve düşey scroll çubuklarına sahip olabilir. List box kontrolü edit
kontrolünde olduğu gibi pek çok işlemi kendi içerisinde yapmaktadır. Örneğin Ctrl+C
tuş kombinasyonuyla aktif satır otomatik olarak clipboard içerisine alınır.
List Box Kontrolünün Pencere Biçimleri
|
LBS_SORT
|
List box kontrolüne eleman eklendiğinde eklenen elemanların sıralı
gözükmesini sağlar.
|
|
LBS_EXTENDEDSEL
|
Uzatmalı list box kontrolü anlamına gelir. Eğer bu pencere biçimi
belirlenirse shift ve ok tuşlarıyla ya da shift ve mouse ile bir elemandan
başlayarak n tane elemanın seçilmesi sağlanabilir. Ancak ayrık seçim
yapılamaz.
|
|
LBS_MULTIPLESEL
|
Ayrık seçilebilme özelliğini kazandırır. Ctrl ve mouse ile birden fazla
seçim yapılabilir.
|
|
LBS_MULTICOLUMN
|
Çok sütunlu list box kontrolü aslında tek sütunlu gibi işlem görür. Sütun
sayısı ayarlanamaz.
|
|
LBS_NOTIFY
|
Mouse ile click ya da double-click yapıldığında üst pencereye mesaj
gönderilmesini sağlar.
|
|
LBS_STANDARD
|
Bu bir sembolik sabittir. #define LBS_STANDARD (LBS_NOTIFY | LBS_SORT |
WS_VSCROLL | WS_BORDER)
|
List Box Kontrolüne Gönderilen Mesajlar
1. List box kontrolüne eleman eklenmesi
Bunun için LB_ADDSTRING
mesajı kullanılır. Mesajın parametreleri:
wParam = 0;
lParam = (LPARAM) str; /*Eklenecek
yazının başlangıç adresi*/
Eğer list box LBS_SORT ile yaratılmışsa otomatik olarak sıralı bir biçimde
listeye eklenir, değilse sona eklenir.
List box mesalarının geri
dönüş değerleri işlemin başarısı hakkında bilgi vermektedir. Geri dönüş değeri
3 biçimde olabilir:
|
LB_ERRSPACE
|
(-2)
|
|
LB_ERR
|
(-1)
|
|
LB_OK
|
(0)
|
Normal olarak bu değerin kontrol edilmesine gerek yoktur.
List box kontrolüne eleman
otomatik olarak yerleştirilemez, ancak bu mesajla yerleştirilebilir. Kontrolün
içerisinde başlangıçta n tane eleman gözükmesi isteniyorsa üst pencerenin
WM_CREATE mesajı içerisinde eleman eklenebilir.
char *names[10] =
{"Ali", "Veli", "....", ...};
WM_CREATE:
hListBox =
CreateWindow(.................);
for (i = 0; i < n; ++i)
SendMessage(hListBox,
LB_ADDSTRING, 0, (LPARAM) names[i])
break;
2. List box kontrolüne eleman insert
edilmesi
Bunun için LB_INSERTSTRING
mesajı kullanılır. Mesaj parametreleri:
wParam = index no;
lParam = (LPARAM) str;
List box içerisindeki ilk eleman 0 olmak üzere her elemana artan sırada bir
sayı karşılık düşürülmüştür. Buradaki index numarası ilki 0 olmak üzere kaç
numaralı satır olduğunu anlatır. Örneğin bu sayı 5 olarak girilmişse insert
edilecek elemanın index numarası 5 olacak biçimde kaydırma yapılır(yani önceki
5 numara 6 olur). List box sıralı olarak oluşturulursa böyle bir ekleme sırayı
bozar.
3. Bir elemanın silinmesi.
Bunun için LB_DELETESTRING
mesajı kullanılır. Mesajın parametreleri:
wParam = index no;
lParam = 0;
Kontrolden bütün
elemanların silinmesi için LB_RESETCONTENTS mesajı kullanılır. wParam ve lParam
parametreleri 0 girilmelidir.
4. Toplam eleman sayısının elde edilmesi.
List box içerisindeki
toplam eleman sayısı, eleman eklenirken programcı tarafından da izlenebilir.
Ancak LB_GETCOUNT msajı ile bu sayı alınabilir. wParam ve lParam 0 olarak
girilir. SendMessage fonksiyonunun geri dönüş değeri toplam eleman sayısını
verir.
5. List box içerisindeki bir elemanın yazısının elde edilmesi
Bunun için LB_GETTEXT
mesajı kullanılır. Mesajın parametreleri:
wParam = index no;
lParam = (LPARAM)
buf;
char buf[50];
SendMessage(hListBox,
LB_GETTEXT, indexno, buf);
6. List box'taki bir elemanın karakter uzunluğunun bulunması
Bunun için LB_GETTEXTLEN
mesajı kullanılır. Mesajın parametreleri:
wParam = index no;
lParam = 0;
Geri dönüş değeri karakter uzunluğudur.
7. List box kontrolündeki aktif elemanın index numarasının tespit edilmesi
Eğer list box
genişletilmiş ve ayrık seçime izin vermeyecek biçimde yaratılmış ise bunun için
LB_GETCURSEL kullanılır. Mesajın parametreleri:
wParam = 0;
lParam = 0;
Fonksiyonun geri dönüş değeri o anda seçili olan list box elemanın index
numarasını verir.
Çoklu seçime izin verilen
list box kontrolü için LB_GETSELITEMS mesajı kullanılır. Mesajın parametreleri:
wParam = maximum eleman sayısı;
lParam = (LPARAM) adr;
Fonksiyonun geri dönüş değeri diziye yerleştirilen index numaraları
sayısıdır.
int selItems[100];
int nOfSel;
nOfSel =
SendMessage(hListBox, LB_GETSELITEMS, 100, (LPARAM) selItems);
8. Diğer list box mesajları
|
WM_SETREDRAW
|
Peşi sıra n tane eleman ekleneceği durumda görüntünün titrememesi için
görüntü güncelleme işlemini kapatır ya da açar. wParam = FALSE girilirse
kapatır, TRUE girilirse açar(lParam = 0).
|
|
LB_SETCURSEL
|
Aktif eleman klavye ya da mouse ile değil doğrudan programlama yoluyla
değiştirilebilir.
|
|
LB_SELECTSTRING
|
bu mesaja bir yazı parametre olarak girilir(lParam), bu yazı ile başlayan
list bos elemanı seçilir.
|
List Box Kontrolünün Üst Pencereye Gönderdiği Mesajlar
Kontrolde bir olay
gerçekleştiğinde üst pencere WM_COMMAND mesajıyla çağırılır. HIWORD(wParam) ne
sebeple, LOWORD(wParam) alt pencere ID değeri, lParam alt pencere handle değeri
olur.
List box kontrolünü
gönderdiği en önemli iki mesaj aktif eleman değiştirildiğinde ya da bir elemana double click yapıldığında
gönderilen mesajlardır. Eğer HIWORD(wParam) = LBN_SELCHANGE ise o anda aktif
eleman değişmiştir, yani eğer LB_GETCURSEL mesajı gönderilirse yeni aktif
elemanın index numarası elde edilir. Eğer HIWORD(wParam) LBN_DBLCLK ise bir
eleman
üzerine double click yapıldığı anlaşılır. Bunun dışında LBN_ERRSPACE,
LBN_SETFOCUS, LBN_KILLFOCUS gibi mesajlar da vardır. Ancak fazla
kullanılmazlar.
List Box mesajlarını incelemek için tipik bir yapı:
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDLIST:
switch(HIWORD(wParam))
{
.........
.........
case
LBN_SELCHANGE:
ProcessSelChange();
break;
case
LBN_DBLCLK:
ProcessDblClk();
break;
}
break;
........
........
........
}
break;
void
ProcessSelChange(void)
{
int index;
index = SendMessage(hListBox,
LB_GETCURSEL, 0, 0);
.....
}
Windows sisteminin burada
ele alınmayan diğer kontrolleri dialog pencereleri konusunda ele alınacaktır.
Ancak diğer kontrollerin yaratılması ve kullanılmasında yukarıda açıklanan aynı
sistematik kullanılmaktadır.
Pencere Parametrelerini Değiştirmek
CreateWindow fonksiyonunda
verilen parametreler user32.dll modülü içerisinde oluşturulan ve pencere
bilgilerini tutan içsel bir veri yapısında tutulurlar. CreateWindow
fonksiyonundan elde edilen handle değeri aslında bu içsel veri yapısının
adresidir. Ancak bu içsel veri yapısı içerisindeki veri yapısı GetWindowLong
fonksiyonuyla elde edilebilir, SetWindowLong fonksiyonuyla değiştirilebilirler.
Pencerenin parametrik bilgileri değiştirildiğinde bu pencereyle ilgili ilk
handle işlemi yapıldığı zaman değişiklik hissedilir. GetWindowLong ve
SetWindowLong fonksiyonlarının kullanımları birbirlerine çok benzer. Prototipleri:
LONG GetWindowLong(
HWND hWnd,
int nIndex
);
LONG SetWindowLong(
HWND hWnd,,
int nIndex,
LONG dwNewLong
);
Fonksiyonların
birinci parametresi parametrik bilgileri değiştirilecek pencerenin handle
değeridir. İkinci parametre pencerenin hangi parametresinin değiştirileceğini
ya da elde edileceğini belirtir.
Örneğin bir pencere WS_BORDER pencere biçimiyle yaratılmamış olsun.
WS_BORDER biçimini bu pencere ekleyebilmek için öncelikle pencerenin pencere
biçimi parametresini elde etmek gerekir. Bu işlem için GWL_STYLE sembolik
sabitini kullanmak gerekir.
dwResult =
GetWindowlong(hWnd, GWL_STYLE);
SetWindowLong(hWnd,
GWL_STYLE, dwResult | WS_BORDER);
WS_BORDER'ı
kaldırmak isteseydik:
SetWindowLong(hWnd,
GWL_STYLE, dwResult & ~WS_BORDER);
Örneğin pencere fonksiyonu içerisinde hInstance değeri şöyle elde
edilebilir:
dwReseult =
GetWindowLong(hWnd, GWL_HINSTANCE);
GWL_WINDOWPROC ile pencere fonksiyonunun başlangıç adresi elde edilebilir.
Elde edilen bu başlangıç adresinin bir fonksiyon göstericisine yerleştirilmesi
gerekir. Normal olarak pencere fonksiyonunun başlangıç adresi uzun bir biçimde
aşağıdaki gibi bir fonksiyon göstericisine atanabilir:
LRESULT(CALLBACK
*p)(HWND, UINT, WPARAM, LPARAM);
p =
(LRESULT(CALLBACK *p)(HWND, UINT, WPARAM, LPARAM))GetWindowLong(hWnd,
GWL_WINDOWPROC);
Ancak
WNDPROC typedef ismi aşağıdaki gibi tanımlanmıştır ve işlemleri kolaylaştırır:
typedef LRESULT
(CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM);
Bu typedef sayesinde yukarıda işlem kolaylaşır:
WNDPROC p;
p = (WNDPROC)GetWindowLong(hWnd,
GWL_WINDOWPROC);
Pencere Fonksiyonunun Hook Edilmesi(Windows
subclassing)
Hooking bir olay sırasında
bir fonksiyon çağırılıyorsa başka bir fonksiyonun çağırılması sağlanarak o
fonksiyonun da önceki fonksiyonu çağırmasıyla bir çeşit araya girme işleminin
oluşturlmasına veriln bir isimdir. Örneğin kontrollerin pencere fonksiyonları
user32.dll içerisindedir. Normal olarak kontrollerle ilgili işlem yapıldığında
kontrolün pencere fonksiyonu çağırılır. Ancak GetWindowLong API fonksiyonuyla
kontrolün pencere fonksiyonunun adresi elde edilebilir. SetWindowLong
fonksiyonuyla programcının pencere fonksiyonu kontrolün pencere fonksiyonu
yerine yazılabilir. Programcının pencere fonksiyonu içerisinde kontrolün
pencere fonksiyonu çağırılabilir. Win32 sistemlerinde prosesler ayrık bir
biçimde belleğe yüklenip çalıştırıldığı için bir prosesin başka bir prosesteki
pencere fonksiyonunu hook edebilmesi normal yöntemlerle mümkün değildir.
SetWindowLong fonksiyonunun geri dönüş değeri ilgili özelliğin değiştirilmesinden
önceki değerdir(GetWindowLong fonksiyonuna gerek yok). Adresi bilinen bir
pencere fonksiyonu doğrudan çağırılabilir. Ancak UNICODE/ASCII
dönüştürülmesinin doğrudan yapılabilmesi için tavsiye edilen yöntem
CallWindowProc API fonksiyonun kullanılmasıdır. Bu durumda push button
kontrolünün hook edilmesi aşağıdaki gibi yapılabilir:
LRESULT CALLBACK
NewProc(HWND, UINT, WPARAM, LPARAM);
WNDPROC pfnOldProc;
hButton =
CreateWindow("button", .............);
pfnOldProc =
(WNDPROC)SetWindowLong(hButton, GWL_WINDOWPROC, (LONG)NewProc);
..
...
LRESULT CALLBACK
NewProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
.......
.......
return
CallWindowProc(pfnOldProc, hWnd, message, wParam, lParam);
}
Dialog Pencereleri
İçerisinde kontrollerin
bulunduğu işletim sistemi tarafından doğrudan desteklenen kaynak tabanlı
çalışan özel pencerelere dialog pencereleri denir. Dialog pencereleri
"modal" ve "modeless" olmak üzere iki kısma ayrılır. Modal
dialog pencereleri DialogBox API fonksiyonuyla açılır, EndDialog API
fonksiyonuyla kapatılır. Modeless dialog pencereleri ise seyrek kullanılır ve
biraz daha değişik organize edilir. Diaolg penceresinin türü ne olursa olsun,
yaratılması için belirli adımlardan geçmek gerekir. Dialog penceresi yaratmanın
ilk adımı rc dosyası içerisinde bir dialog kaynağı yazmaktır. Dialog kaynağının
ismi alfabetik ya da sayısal olarak istenilen biçimde verilebilir. Bu isimden
sonra dialog anahtar sözcüğü kullanılmalıdır. Daha sonra blok içerisinde dialog
penceresi içerisine yerleştirilecek kontrollerin türleri, koordinat
parametreleri, alt pencere ID değerleri, pencere biçimleri belirlenen bir
syntax biçimine uygun olarak yazılır. Dialog kaynağının oluşturulması manual
yöntemnle yapılabileceği gibi kaynak editörleriyle görsel bir biçimde de
yapılabilir. Bundan sonra dialog penceresini yaratan API fonksiyonu
çağırılmalıdır. Bu API fonksiyonları dialog kaynağının ismini parametre olarak
alır. Dialog penceresi içerisine yerleştirilecek kontrolleri tek tek
CreateWindow API fonksiyonunu kullanarak yaratır. Modal dialog pencereleri için
DialogBox, modeless dialog pencereleri için CreateDialog API fonksiyonları
kullanılmaktadır. Modal bir dialog penceresini kapatmak için EndDialog,
modeless bir dialog penceresini kapatmak içinse doğrudan DestroyWindow API
fonksiyonları kullanılır. Dialog pencereleri bir grup kontrolün kolay bir
biçimde yaratılmasını sağlamak için tasarlanmıştır. Bir grup kontrolü doğrudan
ana pencerenin içerisinde oluşturmak yerine başka bir pencerenin içerisinde oluşturmak
çeşitli kullanım kolaylıkları sağlamaktadır.

0 yorum: