| Bu yazımızda, daha
  önce incelemiş olduğumuz düğme kontrollerini kullandığımız bir uygulama geliştireceğiz.
  Uygulamamız, kullanıcıdan öğrencilerin isim ve cinsiyet bilgilerini alacak.
  Bu bilgilerin yanısıra öğrencinin belli kurslardan hangilerini aldığını, hangilerini
  almadığı bilgisini de alacak. Kullanıcıdan aldığı bu bilgileri bir dosyaya kaydedecek.
  Windows API yazı dizimizde daha önce statik kontrolleri ve
  yazı kutusu kontrollerini incelemiştik. Bu uygulamamızda o kontrollerden de
  yararlanacağız. Ana penceremizde dört statik kontrol ve iki yazı kutusu kontrolümüz
  olacak. Bunun yanısıra, bir basma düğmesi, iki seçenek düğmesi, üç seçenek kutusu
  ve bir de grup kutusu oluşturarak düğme kontrollerinin uygulama içerisinde nasıl
  kullanıldığını göreceğiz. 
 Öğrenci bilgilerini
  uygulamanın ana penceresindeki kontrollerden kolay bir biçimde alabilmek için
  bir yapı tanımlayalım. Böylece, kullanıcı kaydı yapmak üzere düğmeye bastığında,
  kontrollerdeki bilgileri tanımladığımız yapı türünden bir nesnenin veri elemanlarına
  atayarak bilgileri dosyaya bu yapı nesnesi aracılığıyla yazabiliriz. Yapımızı,
  uygulamamızın başlık dosyasında şöyle tanımlayalım :
 
 
 
  Ana penceremizde
  tüm bu veri elemanlarına atayacağımız değerleri tutan kontrollerimiz olacak.
  Ana penceremizi oluşturma kısmını, daha önceki yazılarımızda ele aldığımız için
  burada tekrar incelemeyeceğiz. Kaynak kod dosyamızın başında, kontrolleri oluştururken
  CreateWindow fonksiyonunun hMenu parametresi yerine geçtiğimiz tanımlayıcı değerleri
  sembolik sabitler olarak tanımlayalım :
    | typedef struct
      _person {     char name[20];
     char surname[20];
     char maleorfemale;
     int lesson1;
     int lesson2;
     int lesson3;
 }Person;
 |  
 
 
  CreateWindow fonksiyonunun
  geri döndürdüğü kontrol tutamaç değerlerini tutmak için uygulamanın global alanında
  HWN türünden nesneler tanımlayalım :
    | #define ID_EDITBOX_1
      101 #define ID_EDITBOX_2 102
 #define ID_LABEL_1 103
 #define ID_LABEL_2 104
 #define ID_LABEL_3 105
 #define ID_LABEL_4 106
 #define ID_RD_BTN_1 107
 #define ID_RD_BTN_2 108
 #define ID_CKB_BTN_1 109
 #define ID_CKB_BTN_2 110
 #define ID_CKB_BTN_3 111
 #define ID_PSH_BTN_1 112
 #define ID_GRP_BTN_1 113
 |  
 
 
  Kullanıcı kaydın
  yapılması için basma düğmesine bastığında çağrılacak fonksiyonun prototip bildirimini
  de global alanda yapalım :
    | static HWND
      hEditBox1, hEditBox2; static HWND hStatic, hGroupBox;
 static HWND hRadioButton1, hRadioButton2;
 static HWND hCheckBox1, hCheckBox2, hCheckBox3;
 static HWND hPushButton;
 |  
 Uygulamamızın WndProc
  pencere fonksiyonunda, WM_CREATE mesajı alındığında (yani ana penceremiz oluştuğunda)
  kontrollerimizi oluşturacağız. Kontroller, belli olaylar oluştuğunda ana pencereye,
  kendi tanımlayıcı değerlerini ve oluşan olayı belirten bir kod değerini içeren
  WM_COMMAND mesajı iletirler. Ana pencerenin pencere fonksiyonunda WM_COMMAND
  mesajı alınması durumunda, bu mesajı gönderen kontrolün tanımlayıcı değerini
  kontrol ederek mesajın basma düğmesi tarafından gönderilip gönderilmediğini
  anlayabiliriz. Eğer mesaj basma düğmesinden geliyorsa ve gönderilme nedeni de
  düğmeye tıklanmış olmasıysa bu durumda prototip bildirimini yapmış olduğumuz
  OnPshButtonClick fonksiyonunu çağırmalıyız. Tüm bu işlemleri yaptığımız pencere
  fonksiyonumuz şu şekildedir :
 
 
 
  Şimdi pencere fonksiyonumuzu
  adım adım inceleyelim :
    | LRESULT CALLBACK
      WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) {
     switch(message) {
        case WM_COMMAND :
           if (LOWORD(wParam) == ID_PSH_BTN_1
      && HIWORD(wParam) == BN_CLICKED)
               OnPshButtonClick();
           break; 
             case WM_CREATE
        :
           hStatic = CreateWindow("static","İsim :",
         WS_CHILD | WS_VISIBLE,
                                            10,50,75,20,hWnd,(HMENU)ID_LABEL_1,
                                            ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
          
        hEditBox1 = CreateWindow("edit","", WS_CHILD | WS_VISIBLE
        | ES_LEFT,
                                               
        100,50,200,20,hWnd,(HMENU)ID_EDITBOX_1,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
          
        hStatic = CreateWindow("static","Soyisim :", WS_CHILD
        | WS_VISIBLE,
                                           
        10,90,75,20,hWnd,(HMENU)ID_LABEL_2,
                                           
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
          
        hEditBox2 = CreateWindow("edit","", WS_CHILD | WS_VISIBLE
        | ES_LEFT,
                                               
        100,90,200,20,hWnd,(HMENU)ID_EDITBOX_2,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
       
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
          
        hStatic = CreateWindow("static","Cinsiyet :", WS_CHILD
        | WS_VISIBLE,
                                               
        10,130,75,20,hWnd,(HMENU)ID_LABEL_3,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
          
        hGroupBox = CreateWindow("button","", WS_CHILD | WS_VISIBLE
        | BS_GROUPBOX,
                                               
        90,110,200,50,hWnd,(HMENU)ID_GRP_BTN_1,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
          
        hRadioButton1 = CreateWindow("button","Bayan", WS_CHILD
        | WS_VISIBLE | BS_AUTORADIOBUTTON,
                                               
        100,130,75,20,hWnd,(HMENU)ID_RD_BTN_1,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
          
        SendMessage(hRadioButton1,BM_SETCHECK,TRUE,0);
 
          
        hRadioButton2 = CreateWindow("button","Erkek",
                                               
        WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
                                               
        200,130,75,20,hWnd,(HMENU)ID_RD_BTN_2,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
       
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
          
        hStatic = CreateWindow("static","Dersler :",
        WS_CHILD | WS_VISIBLE,
                                               
        10,170,75,20,hWnd,(HMENU)ID_LABEL_4,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
          
        hCheckBox1 = CreateWindow("button","1. Kurs", WS_CHILD
        | WS_VISIBLE | BS_AUTO3STATE,
                                               
        100,170,100,20,hWnd,(HMENU)ID_CKB_BTN_1,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
          
        hCheckBox2 = CreateWindow("button","2. Kurs",
        WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
                                               
        100,200,100,20,hWnd,(HMENU)ID_CKB_BTN_2,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
          
        hCheckBox3 = CreateWindow("button","3. Kurs",
        WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
                                               
        100,230,100,20,hWnd,(HMENU)ID_CKB_BTN_3,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
       
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
          
        hPushButton = CreateWindow("button","Kaydet",
        WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                               
        150,270,100,20,hWnd,(HMENU)ID_PSH_BTN_1,
                                               
        ((LPCREATESTRUCT)lParam)->hInstance,NULL);
 
          
        break;
 
       
        case WM_DESTROY :
           PostQuitMessage(0);
           break;
        default :
           return DefWindowProc(hWnd,message,wParam,lParam);
     }
     return 0;
 }
 
 
 
 |  
 Pencere fonksiyonunda
  WM_COMMAND mesajının alınması durumunda, mesajın basma düğmesi kontrolü tarafından
  gönderilip gönderilmediğini, eğer basma düğmesi kontrolü tarafından gönderilmişse
  kullanıcının düğmeye basmış olması nedeniyle mi gönderildiğini kontrol ediyoruz.
  WM_COMMAND mesajının wParam parametresinin düşük anlamlı WORD değeri, mesajı
  ileten kontrolün tanımlayıcı değerini içerir. Yüksek anlamlı WORD değeri ise
  mesajın gönderilme nedenine ilişkin bir değer belirtir. LOWORD ve HIWORD makroları
  kullanılarak wParam parametresinin düşük ve yüksek anlamlı WORD değerleri elde
  edilebilir. Eğer LOWORD(wParam) değeri ID_PSH_BTN_1 değerine eşitse, mesaj basma
  düğmesi kontrolümüz tarafından gönderilmiştir. Eğer HIWORD(wParam) değeri BN_CLICKED
  değerine eşitse kulanıcı düğmeye basmıştır ve mesaj da bu nedenle iletilmiştir.
  Hatırlayacağınız üzere düğme kontrolleri, basılma sırasında ana pencereye BN_CLICKED
  mesajı iletiyorlardı. Bu koşulların sağlanması durumunda OnPshButtonClick isimli
  fonksiyonumuzu çağırıyoruz. Bu fonksiyonda, alınan bilgileri bir dosyaya kaydedeceğiz.
 
 Pencere fonksiyonunda
  WM_CREATE mesajının alınması durumunda, kullanıcıdan bilgileri almak üzere kullanacağımız
  standart kontrollerimizi oluşturacağız. Öncelikle isim bilgisini almak için
  bir statik konrol ve hemen yanında bir yazı kutusu kontrolü oluşturduk. Hemen
  ardından soyadı bilgisini almak için bir statik kontrol ve hemen yanında bir
  yazı kutusu kontrolü daha oluşturduk. Şimdi cinsiyet bilgisini almak için bir
  ’Cinsiyet’ başlıklı statik kontrol oluşturuyoruz. Bu statik kontrolün yanında,
  birisi ’Bayan’ birisi ’Erkek’ başlıklarına sahip iki seçenek düğmesi oluşturuyoruz.
  Seçenek düğmelerini ’button’ pencere sınıf ismini kullanarak oluşturduk. Seçenek
  düğmesi oluşturduğumuzu belirtmek için de, pencere biçimi parametresinde BS_AUTORADIOBUTTON
  veya BS_RADIOBUTTON sembolik sabirlerinden birini belirtmemiz gereklidir. Kullanıcının
  bu düğmelere basması durumunda yapılması gereken değişiklikleri sisteme bırakmak
  için BS_AUTORADIOBUTTON sembolik sabitini kullanıyoruz. Seçenek düğmelerini
  bir grup kutusu içerisinde göstermek için bu adımda bir de grup kutusu kontrolü
  oluşturduk. Bu kontrol için de ’button’ pencere sınıf ismini kullandık, pencere
  biçimi parametresinde grup kutusu kontrolü oluşturmak istediimizi belirtmek
  amacıyla BS_GROUPBOX sembolik sabitini belirttik. Bu kontrole de bir başlık
  yazısı belirtmemiz mümkündür, bu uygulama için başlık parametresini boş geçtik.
  Şimdi seçenek düğmelerimiz bir grup kutusu içerisinde görüntülenecek.
 
 Öğrencinin aldığı
  kursların işaretlenmesi için bu adımda üç tane seçenek kutusu kontrolü oluşturduk.
  Seçenek kutusu kontrolü de ’button’ pencere sınıf ismi kullanılarak oluşturulur.
  Pencere biçimi parametresinde ise BS_AUTOCHECKBOX, BS_CHECKBOX, BS_3STATE veya
  BS_AUTO3STATE sembolik sabiti belirtilir. Yine işaretlenme işlemlerini sisteme
  bırakmak üzere BS_AUTOCHECKBOX sembolik sabitini kullanmayı tercih ettik. Sadece
  ilk seçenek kutusunu oluştururken BS_AUTO3STATE sembolik sabitini kullanarak
  diğerleri ile arasındaki farkı inceleyelim.
 
 Son olarak bir
  de basma düğmesi oluşturalım. Bu düğme kayıt bilgilerinin tamamen girildiğini
  ve artık kaydın yapılabileceğini belirtmek amacıyla kullanılacak. Basma düğmeleri
  oluştururken de ’button’ pencere sınıf ismi kullanılır. Pencere biçimi parametresinde
  ise BS_PUSHBUTTON veya BS_DEFPUSHBUTTON sembolik sabitleri belirtilir. Kullanıcının
  bu basma düğmesine basması durumunda OnPshBtnClick fonksiyonumuz çağrılacak.
  Ekrandaki bilgileri alarak Person türünden bir yapı nesnesinin veri elemanlarına
  yazan ve sonra bu yapı nesnesinin veri elemanlarının değerini bir dosyaya aktaran
  SavePersonRecord isimli bir fonksiyon daha yazıyoruz. OnPshBtnClick fonksiyonunda,
  yazmış olduğumuz bu fonksiyonu çağırıyoruz. OnPshBtnClick fonksiyonumuz şöyle
  olacak :
 
 
 
  Şimdi SavePersonRecord
  fonksiyonumuza bakalım :
    | void OnPshButtonClick() {
     SavePersonRecord();
 }
 |  
 
 
  SavePersonRecord
  fonksiyonu, BOOL
  türden bir değer döndürüyor. Kaydın başarıyla yapılması durumunda TRUE değerini,
  başarısızlık durumunda ise FALSE değerini döndürecek. Bu fonksiyon içerisinde
  ControlForm ve ClearForm isimli iki fonksiyon daha çağırdık. Bu fonksiyonlar
  sırasıyla, girilen bilgilerin tam olup olmadığını kontrol ediyor ve kayıt başarıyla
  tamamlandıktan sonra ana penceredeki kontrollerin değerlerini sıfırlayarak formu
  yeni bir kayıt için hazılıyor. ControlForm fonksiyonu kişiye ait isim ve soyisim
  bilgilerinin girilip girilmediğini kontrol ediyor. Eğer bu fonksiyondan FALSE
  değeri dönerse MessageBox API fonksiyonu ile kullanıcıya bir hata mesajı iletiliyor.
  Eğer bu fonksiyondan TRUE değeri dönerse kayda devam ediliyor. Fonksiyonumuzun
  başında Person türünden bir yapı nesnesi tanımladık. Kullanıcının girdiği değerleri
  bu nesnenin veri elemanlarına aktaracağız. Sırasıyla isim ve soyisim alanlarına
  girilen değerler GetWindowText API fonksiyonu ile Person türünden yapı nesnemizin
  name ve surname isimli veri elemanlarına aktarılıyor. Ardından cinsiyet bilgisinin
  öğrenilmesi için seçenek düğmelerinin işaretlenme durumları inceleniyor. İlk
  seçenek düğmesine SendMessage API fonksiyonu ile BM_GETCHECK mesajı iletiliyor.
  SendMessage fonksiyonu bu mesajın iletilmesiyle bize kontrolün işaretli olup
  olmadığını belirten bir değer döndürecek. Kontrol işaretlenmişse 1 değeri, işaretlenmemişse
  0 değeri döndürülür. Alınan bu bilgi kontrol edilerek, nesnenin maleorfemale
  veri elemanına ’f’ veya ’m’ değeri atanıyor. Burada her iki seçenek düğmesinin
  işaret durumunun da kontrol edilmesine gerek yoktur. Çünkü aynı anda bu seçenek
  düğmelerinden sadece birisi işaretli olabilir. Öğrencinin hangi kursları aldığını
  seçmek için oluşturduğumuz seçenek kutularının işaret durumları da kontrollere
  BM_GETCHECK mesajı gönderilerek öğreniliyor. Eğer fonksiyondan 1 değeri dönerse
  yapı nesnemizin ilgili veri elemanına 1 değerini, aksi takdirde 0 değerini atıyoruz.
  Tüm bilgileri yapı nesnemize aktardıktan sonra şimdi dosyaya yazma işlemine
  geçebiliriz. Bu amaçla (FILE *) türünden fpisimli nesnemize fopen fonksiyonu
  ile vir tutamaç değeri atıyoruz ve dosyamızı sona ekleme modunda açıyoruz. fopen
  çağrısından snra fp nesnemizin değeri NULL olursa dosya açma işlemi başarısız
  olmuş demektir. Eğer bu durum gerçeklenirse fonksiyondan FALSE değeri ile dönüyoruz.
  Dosya başarıyla açılmışsa nesnedeki değerleri formatlı bir şekilde dosyaya yazıyoruz.
  Yazma işlemi tamamlandıktan sonra kullanıcıya MessageBox API fonksiyonu ile
  bilgi veriyoruz. Sonra formu temizlemek için ClearForm fonksiyonunu çağırıyoruz
  ve TRUE değeri ile fonksiyondan dönüyoruz.
    | BOOL SavePersonRecord() {
     LRESULT checked, les1, les2, les3;
     Person person;
     FILE *fp; 
          
        if (ControlForm() == FALSE) {
         MessageBox(NULL,"İsim veya soyisim
        bilgisi eksik","Hata",MB_OK);
         return FALSE;
     }
 
    
        GetWindowText(hEditBox1,&person.name,20);
     GetWindowText(hEditBox2,&person.surname,20);
     checked = SendMessage(hRadioButton1,BM_GETCHECK,0,0);
     person.maleorfemale = checked == TRUE ? ’F’ : ’M’;
 
     les1 = SendMessage(hCheckBox1,BM_GETCHECK,0,0);
     person.lesson1 = les1 == TRUE ? 1 : 0;
     les2 = SendMessage(hCheckBox2,BM_GETCHECK,0,0);
     person.lesson2 = les2 == TRUE ? 1 : 0;
     les3 = SendMessage(hCheckBox3,BM_GETCHECK,0,0);
     person.lesson3 = les3 == TRUE ? 1 : 0;
 
    
        fp = fopen("person.txt","a");
     if (fp == NULL)
         return FALSE;
     fprintf(fp,"%-20s %-20s %c %d %d %d",person.name,person.surname,person.maleorfemale,
     person.lesson1,person.lesson2,person.lesson3);
     fputc(’\n’,fp);
     fclose(fp);
 
    
        MessageBox(NULL,"Kayıt Yapıldı","Bilgi",MB_OK);
     ClearForm();
     return TRUE;
 }
 
 
 |  
 Son olarak ControlForm
  ve ClearForm isimli fonksiyonlarımızı da inceleyelim :
 
 
 
  ControlForm fonksiyonunda,
  isim ve soyisim alanlarına girilen değerleri kontrol ederek, bu değerleri standart
  strcmp fonksiyonunu kullanarak boş bir karakter katarı ile karşılaştırıyoruz.
  Eğer isim veya soyisim alanlarından birisi boş bırakılmışsa fonksiyon FALSE
  değeri ile, her iki alan da doldurulmuşsa TRUE değeri ile fonksiyondan dönüyoruz.
  ClearForm fonksiyonunda ise, isim ve soyisim alanlarını SetWindowText API fonksiyonunu
  boş bir karakter katarı parametresiyle çağırarak temizliyoruz. Seçenek düğmelerini
  ilk haline getirmek için, kontrollere SendMessage API fonksiyonu ile BM_SETCHECK
  mesajı gönderiyoruz. wParam parametresi olarak, ilk seçenek düğmesi için kontrolün
  işaretli olmasını sağlamak amacıyla TRUE değerini; ikinci seçenek düğmesi için
  kontrolün seçili olmamasını sağlamak amacıyla FALSE değerini kullanıyoruz. Seçenek
  kutularının başlangıçta işaretli olmamalarını sağlamak için üç kontrole de SendMessage
  API fonksiyonu ile BM_SETCHECK mesajı iletiyoruz ve wParam parametresi olarak
  FALSE değerini geçiyoruz. Şimdi ana penceremiz yeni bir kayda hazır durumdadır.
    | BOOL ControlForm() {
     char name [20], surname [20];
     GetWindowText(hEditBox1,name,20);
     GetWindowText(hEditBox2,surname,20); 
          
        if (strcmp(name,"") == 0 || strcmp(surname,"") ==
        0)
         return FALSE;
     return TRUE;
 }
 
 BOOL ClearForm()
 {
     SetWindowText(hEditBox1,"");
     SetWindowText(hEditBox2,"");
     SendMessage(hRadioButton1,BM_SETCHECK,TRUE,0);
     SendMessage(hRadioButton2,BM_SETCHECK,FALSE,0);
     SendMessage(hCheckBox1,BM_SETCHECK,FALSE,0);
     SendMessage(hCheckBox2,BM_SETCHECK,FALSE,0);
     SendMessage(hCheckBox3,BM_SETCHECK,FALSE,0);
 }
 
 
 
 |  
 Uygulamamızın çalışır
  haldeki görünümü şu şekilde olacaktır :
 
 
  
 İsim veya soyisim
  alanlarından herhangi birisinin boş bırakılması durumunda karşılaşacağımız mesaj
  :
 
 
  
 Kaydın başarıyla
  tamamlanması durumunda karşılaşacağımız mesaj ise :
 
 
  
 şeklinde olacaktır.
  Bu uygulamamızda düğme kontrollerinin nasıl oluşturulduğunu, nasıl kullanıldığını,
  düğme kontrollerine gönderilen mesajları ve kontrolden gelen mesajların işlenmesini
  inceledik. Oluşturduğumuz uygulamada daha önce incelemiş olduğumuz standart
  kontrollerden de oluşturarak bu kontroller hakkındaki bilgilerimizi tazeledik.
  Uygulaya ait kaynak kod dosyalarını buradan
  indirebilirsiniz. (Uygulama Microsoft .NET 2003’te hazırlanmıştır.) Yeni bir
  yazımızda daha görüşmek üzere herkese mutlu günler dilerim.
 
 
 
                Makale:Windows API - Düğme Kontrolleri Uygulaması C ve Sistem Programlama Çiğdem Çavdaroğlu
 |