push button kontrolü

2 Temmuz 2013 Salı Unknown 0 yorum

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: