BG MVC Model View Controller eğitim serisi yayında...

Ana page > Programlama > Windows API Programlama > ComboBox

ComboBox

► Kontroller

  • ComboBox kontrolü oluşturma
  • ComboBox eleman değerini değiştirme
  • ComboBox kontrolü oluşturma

    Combo Box, kullanıcının içinden bir seçeneği seçebileceği, bir Edit kontrolü ve bir List Box kontrolünün özelliklerini birleştiren bir kontrol penceresidir.

    Combo Box kontrolü, CreateWindowEx() fonksiyonunun lpClassName parametresi içinde COMBOBOX veya WC_COMBOBOX değeri ile tanımlanan bir kontroldür.

    COMBOBOX değerini kullanırsanız programın başında windows.h başlık dosyasını dahil etmeniz yeterlidir, ancak WC_COMBOBOX değerini kullanırsanız commctrl.h başlık dosyasını dahil etmeniz gerekir.

    Şimdi, programımıza COMBOBOX kontrolleri eklemeye çalışalım.

    Aşağıdaki satırlar programın başına global değerler olarak eklenir:

    
    /* Combo Box kontrolleri için tanımlayıcı makro bildirimleri */
    #define IDC_COMBOBOX01 501 
    #define IDC_COMBOBOX02 502
    #define IDC_COMBOBOX03 503
    
    /* Combo Box kontrolü için pencere Handle değeri bildirimi */
    HWND hwndComboBox01, hwndComboBox02, hwndComboBox03;
    
    /* İsim değerleri için char dizi bildirimi */
    char isim[][20] = 
    { 
      "Ahmet", "Mehmet", "Yasemin", "Faruk", "Necip", "Ayşe", " "
    };
    
    

    WindowProcedure() fonksiyonu içinde renkli olarak gösterilen satırlar ile bir Combo Box kontrolü oluşturulur. WM_COMMAND mesajına işlem yapılarak Combo Box kontrolü ile ilgili işlemler belirlenir:

    
    LRESULT CALLBACK WindowProcedure (HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
    {
      int id1;
      char cdizi[20];
      
      switch (message)
      { 
        case WM_CREATE:
    
             hwndStatic01 = CreateWindowEx(0, "STATIC", "Statik kontrol",
                                    WS_CHILD | WS_VISIBLE | SS_LEFT, 20, 20, 300, 20,
                                    hwnd, (HMENU) IDC_STATIC01, NULL, NULL);
    	
             hwndComboBox01 = CreateWindowEx(0, "COMBOBOX", NULL,
                                 WS_CHILD | WS_VISIBLE | CBS_SIMPLE, 20, 50, 120, 150,
                                 hwnd, (HMENU) IDC_COMBOBOX01, NULL, NULL);
    							 
             hwndComboBox02 = CreateWindowEx(0, "COMBOBOX", NULL,
                                 WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, 200, 50, 120, 150,
                                 hwnd, (HMENU) IDC_COMBOBOX02, NULL, NULL);
    
             hwndComboBox03 = CreateWindowEx(0, "COMBOBOX", NULL,
                                 WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 380, 50, 120, 150,
                                 hwnd, (HMENU) IDC_COMBOBOX03, NULL, NULL);
    
             for (id1=0; strcmp (isim[id1], " "); id1++) {
                  SendMessage(hwndComboBox01, CB_ADDSTRING, 0, (LPARAM) isim[id1]);
                  SendMessage(hwndComboBox02, CB_ADDSTRING, 0, (LPARAM) isim[id1]);
                  SendMessage(hwndComboBox03, CB_ADDSTRING, 0, (LPARAM) isim[id1]);
             }
    		 
             SendMessage(hwndComboBox01, CB_SETCURSEL, 0, 0);
             SendMessage(hwndComboBox02, CB_SETCURSEL, 0, 0);
             SendMessage(hwndComboBox03, CB_SETCURSEL, 0, 0);
    		 
             break;
    
        case WM_COMMAND:
    	   
             if (HIWORD(wParam) == CBN_SELCHANGE) {
                 SendMessage((HWND)lParam, CB_GETLBTEXT, SendMessage((HWND) lParam,
                             CB_GETCURSEL, 0, 0), (LPARAM) cdizi);
                 SetWindowText(hwndStatic01, cdizi);
             }          
    	  
             break;
    		 
        case WM_DESTROY:
             PostQuitMessage (0);
             break;
    		 
        default:                 
             return DefWindowProc (hwnd, message, wParam, lParam);
      }
    
      return 0;
    }
    
    

    Programda, aşağıda özellikleri açıklanan 3 farklı tipte Combo Box oluşturulur:

    CBS_SIMPLE : Liste içinde yer alan elemanları daima ekranda gösterir. Seçili olan elemanı ise bir Edit kontrolü içinde gösterir.

    CBS_DROPDOWN : Liste içinde yer alan elemanları düğmeye tıklandığında ekranda gösterir. Seçili olan elemanı ise bir Edit kontrolü içinde gösterir.

    CBS_DROPDOWNLIST : Liste içinde yer alan elemanları düğmeye tıklandığında ekranda gösterir. Seçili olan elemanı ise bir Statik kontrol içinde gösterir.

    Combo Box kontrol penceresi oluşturulurken, CreateWindowEx() fonksiyonunun lpClassName parametresi için sistemdeki ön tanımlı değerlerden biri olan COMBOBOX değeri, dwStyle parametresinde ise sırasıyla CBS_SIMPLE, CBS_DROPDOWN, CBS_DROPDOWNLIST değerleri kullanılır.

    Program çalıştığında:

    • Program penceresi oluşturulur oluşturulmaz WM_CREATE mesajı mesaj işlem fonksiyonuna gönderilir. switch yapısının bu seçeneği altında CreateWindowEx() fonksiyonu ile bir adet Static kontrol ve 3 farklı tipte Combo Box kontrolü oluşturulur.
    • Tüm Combo Box pencerelerine bir for döngüsü içinde CB_ADDSTRING mesajı sıra ile gönderilerek, isim adlı char dizi içindeki değerler Combo Box kontrollerine aktarılır.
    • Combo Box pencerelerine bir CB_SETCURSEL mesajı gönderilerek, kontrol içindeki ilk elemanlar seçilir.
    • Kontroller tarafından ana pencereye gönderilen bildirim mesajlarına işlem yapmak üzere ana pencere mesaj işlem fonksiyonu içinde oluşturulan WM_COMMAND seçeneği altında CBN_SELCHANGE bildirim mesajı geldiğinde, kullanıcının Combo Box kontrolü üzerine yaptığı tıklamaların karşılığı olan gerekli işlemler yapılır:
      • Önce, Combo Box kontrol penceresine CB_GETCURSEL mesajı gönderilerek seçilen elemanın sıfırdan başlamak üzere indeks değeri alınır.
      • Elde edilen değer kullanılarak, Combo Box kontrol penceresine CB_GETLBTEXT mesajı gönderilerek seçilen elemanın metin değeri elde edilir.
      • Elde edilen değer SetWindowText() fonksiyonu ile Statik kontrol penceresine yazılır.

    Programın çalışan en son hali aşağıdadır:

    
    #include <windows.h>
    
    #define IDC_STATIC01 101
    #define IDC_COMBOBOX01 501
    #define IDC_COMBOBOX02 502
    #define IDC_COMBOBOX03 503
    
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    char szClassName[ ] = "WinAPIWindowsApp";
    HINSTANCE ghInst;
    
    HWND hwndStatic01;
    HWND hwndComboBox01, hwndComboBox02, hwndComboBox03;
    
    char isim[][20] = 
    { 
      "Ahmet", "Mehmet", "Yasemin", "Faruk", "Necip", "Ayşe", " "
    };
    
    int WINAPI WinMain (HINSTANCE hThisInstance, 
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nCmdShow)
    {
      HWND hwndMain;         
      MSG messages;      
      WNDCLASSEX wincl;
    
      ghInst = hThisInstance;
    
      wincl.hInstance = hThisInstance;
      wincl.lpszClassName = szClassName;
      wincl.lpfnWndProc = WindowProcedure;
      wincl.style = CS_DBLCLKS;           
      wincl.cbSize = sizeof (WNDCLASSEX);
    
      wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
      wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
      wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
      wincl.lpszMenuName = NULL; 
      wincl.cbClsExtra = 0; 
      wincl.cbWndExtra = 0; 
      wincl.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    
      if (!RegisterClassEx (&wincl)) return 0;
    
      hwndMain = CreateWindowEx (0, szClassName, "WinAPI Temel Program", WS_OVERLAPPEDWINDOW, 
                             CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, 
                             hThisInstance, NULL);
    						 
      if (!hwndMain) return 0;
    
      ShowWindow (hwndMain, nCmdShow);
      UpdateWindow(hwndMain);
      
      while (GetMessage (&messages, NULL, 0, 0) > 0) {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
      }	
    	
      return messages.wParam;
    }
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
    {
      int id1;
      char cdizi[20];
      
      switch (message)
      { 
        case WM_CREATE:
    
             hwndStatic01 = CreateWindowEx(0, "STATIC", "Statik kontrol",
                                    WS_CHILD | WS_VISIBLE | SS_LEFT, 20, 20, 300, 20,
                                    hwnd, (HMENU) IDC_STATIC01, NULL, NULL);
    	
             hwndComboBox01 = CreateWindowEx(0, "COMBOBOX", NULL,
                                 WS_CHILD | WS_VISIBLE | CBS_SIMPLE, 20, 50, 120, 150,
                                 hwnd, (HMENU) IDC_COMBOBOX01, NULL, NULL);
    							 
             hwndComboBox02 = CreateWindowEx(0, "COMBOBOX", NULL,
                                 WS_CHILD | WS_VISIBLE | CBS_DROPDOWN, 200, 50, 120, 150,
                                 hwnd, (HMENU) IDC_COMBOBOX02, NULL, NULL);
    
             hwndComboBox03 = CreateWindowEx(0, "COMBOBOX", NULL,
                                 WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 380, 50, 120, 150,
                                 hwnd, (HMENU) IDC_COMBOBOX03, NULL, NULL);
    
             for (id1=0; strcmp (isim[id1], " "); id1++) {
                  SendMessage(hwndComboBox01, CB_ADDSTRING, 0, (LPARAM) isim[id1]);
                  SendMessage(hwndComboBox02, CB_ADDSTRING, 0, (LPARAM) isim[id1]);
                  SendMessage(hwndComboBox03, CB_ADDSTRING, 0, (LPARAM) isim[id1]);
             }
    		 
             SendMessage(hwndComboBox01, CB_SETCURSEL, 0, 0);
             SendMessage(hwndComboBox02, CB_SETCURSEL, 0, 0);
             SendMessage(hwndComboBox03, CB_SETCURSEL, 0, 0);
    		 
             break;
    
        case WM_COMMAND:
    	   
             if (HIWORD(wParam) == CBN_SELCHANGE) {
                 SendMessage((HWND)lParam, CB_GETLBTEXT, SendMessage((HWND) lParam,
                             CB_GETCURSEL, 0, 0), (LPARAM) cdizi);
                 SetWindowText(hwndStatic01, cdizi);
             }          
    	  
             break;
    		 
        case WM_DESTROY:
             PostQuitMessage (0);
             break;
    		 
        default:                 
             return DefWindowProc (hwnd, message, wParam, lParam);
      }
    
      return 0;
    }
    
    

    Program çalıştığında karşınıza gelecek ekran görüntüsü aşağıdadır:

    ComboBox eleman değerini değiştirme

    Bir ComboBox kontrolunu CBS_DROPDOWNLIST parametresi ile oluşturup içine elemanlar eklediğimizde, Windows tarafından sağlanan ComboBox_GetLBText() makrosunu kullanarak, ComboBox içindeki elemanlardan herhangi birinin karakter dizisi değerini elde edebiliriz. Ancak, elde ettiğimiz bu değerlerin değiştirilmesi için herhangi bir makro bulunmamaktadır.

    Bir ComboBox kontrolünün elemanlarından herhangi birini veya seçili olan değeri değiştirmek için, ComboBox_GetCurSel(), ComboBox_DeleteString(), ComboBox_InsertString() ve ComboBox_SetCurSel() makrolarını birlikte kullanabiliriz.

    1. Öncelikle burada gösterildiği gibi bir Windows API projesi oluşturalım. Projeyle birlikte otomatik olarak oluşturulan main.c dosyası içine aşağıda gösterilen kodları ekleyelim:

    
    #define IDC_BUTTON 101
    
    #include <tchar.h>
    #include <windows.h>
    #include <windowsx.h> /* ComboBox makroları için */
    
    /*  Declare Windows procedure  */
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    /*  Make the class name into a global variable  */
    TCHAR szClassName[ ] = _T("DenemeApp");
    
    HWND hwndComboBox, hwndButton;
    void ChangeComboBoxItem(void);
    
    case WM_CREATE:
         /* ComboBox oluşturma */
         hwndComboBox = CreateWindowEx(0, "COMBOBOX", NULL,
                             WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 20, 20, 120, 150,
                             hwnd, 0, NULL, NULL);
    
         SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item01");
         SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item02");
         SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item03");
         SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item04");
         SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item05");
    
         SendMessage(hwndComboBox, CB_SETCURSEL, 0, 0);
    
         hwndButton = CreateWindowEx(0, "BUTTON", "Değer değiştir", /* Buton oluşturma */
                                     WS_CHILD | WS_VISIBLE, 150, 20, 120, 24,
                                     hwnd, (HMENU) IDC_BUTTON, NULL, NULL);
         break;
    	 
    case WM_COMMAND:
    
         if (HIWORD(wParam) == BN_CLICKED) {
             if (LOWORD(wParam) == IDC_BUTTON) {
                 ChangeComboBoxItem(); /* ComboBox seçili değerini değiştirme */
             }
         }
         break;	 
    
    

    ComboBox makrolarının kullanılabilmesi için programın başına windowsx.h başlık dosyası eklenir.

    Yukarıdaki kodlarla, önce bir ComboBox kontrolu oluşturulur ve 5 adet eleman eklenir.

    Bir adet buton kontrolu oluşturulur.

    Butona tıkladığımızda, ChangeComboBoxItem() fonksiyonu ile ComBoBox kontrolu seçili değeri "Yeni değer" ifadesi ile değiştirilir.

    
    void ChangeComboBoxItem(void)
    {
      int cbindex;
      char cdizi[20];
    
      strcpy(cdizi, "Yeni değer");
    
      cbindex = ComboBox_GetCurSel(hwndComboBox); /* ComboBox seçili eleman indeksini alma */
    
      ComboBox_DeleteString(hwndComboBox, cbindex); /* ComboBox seçili elemanı listeden silme */
      ComboBox_InsertString(hwndComboBox, cbindex, cdizi); /* ComboBox silinen eleman indeksine yeni bir eleman ekleme */
      ComboBox_SetCurSel(hwndComboBox, cbindex); /* ComboBox yeni elemanı seçme */
    }
    
    

    ChangeComboBoxItem() fonksiyonu ile önce cdizi karakter dizisine "Yeni değer" ifadesi atanır.

    ComboBox_GetCurSel() makrosu ile ComBoBox kontrolu seçili eleman değeri indeksi alınır.

    ComboBox_DeleteString() makrosu ile seçili eleman ComboBox kontrolu listesinden silinir.

    ComboBox_InsertString() makrosu ile cdizi değeri ComboBox kontrolüne silinen eleman indeksi ile eklenir.

    ComboBox_SetCurSel() makrosu ile yeni eklenen eleman seçilir.

    Yukarıdaki kodların tamamını eklediğimizde, main.c dosyasının en son hali aşağıdaki şekilde olacaktır.

    main.c

    
    #if defined(UNICODE) && !defined(_UNICODE)
        #define _UNICODE
    #elif defined(_UNICODE) && !defined(UNICODE)
        #define UNICODE
    #endif
    
    #define IDC_BUTTON 101
    
    #include <tchar.h>
    #include <windows.h>
    #include <windowsx.h> /* ComboBox makroları için */
    
    /*  Declare Windows procedure  */
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    
    /*  Make the class name into a global variable  */
    TCHAR szClassName[ ] = _T("DenemeApp");
    
    HWND hwndComboBox, hwndButton;
    void ChangeComboBoxItem(void);
    
    int WINAPI WinMain (HINSTANCE hThisInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR lpszArgument,
                         int nCmdShow)
    {
        HWND hwnd;               /* This is the handle for our window */
        MSG messages;            /* Here messages to the application are saved */
        WNDCLASSEX wincl;        /* Data structure for the windowclass */
    
        /* The Window structure */
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
        wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
        wincl.cbSize = sizeof (WNDCLASSEX);
    
        /* Use default icon and mouse-pointer */
        wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL;                 /* No menu */
        wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        /* Use Windows's default colour as the background of the window */
        wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    
        /* Register the window class, and if it fails quit the program */
        if (!RegisterClassEx (&wincl))
            return 0;
    
        /* The class is registered, let's create the program*/
        hwnd = CreateWindowEx (
               0,                       /* Extended possibilites for variation */
               szClassName,             /* Classname */
               _T("Deneme Uygulaması"), /* Title Text */
               WS_OVERLAPPEDWINDOW,     /* default window */
               CW_USEDEFAULT,           /* Windows decides the position */
               CW_USEDEFAULT,           /* where the window ends up on the screen */
               500,                     /* The programs width */
               375,                     /* and height in pixels */
               HWND_DESKTOP,            /* The window is a child-window to desktop */
               NULL,                    /* No menu */
               hThisInstance,           /* Program Instance handler */
               NULL                     /* No Window Creation data */
               );
    
        /* Make the window visible on the screen */
        ShowWindow (hwnd, nCmdShow);
    
        /* Run the message loop. It will run until GetMessage() returns 0 */
        while (GetMessage (&messages, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&messages);
            /* Send message to WindowProcedure */
            DispatchMessage(&messages);
        }
    
        /* The program return-value is 0 - The value that PostQuitMessage() gave */
        return messages.wParam;
    }
    
    /*  This function is called by the Windows function DispatchMessage()  */
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)                  /* handle the messages */
        {
            case WM_CREATE:
                 /* ComboBox oluşturma */
                 hwndComboBox = CreateWindowEx(0, "COMBOBOX", NULL,
                                     WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 20, 20, 120, 150,
                                     hwnd, 0, NULL, NULL);
    
                 SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item01");
                 SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item02");
                 SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item03");
                 SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item04");
                 SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM) "Item05");
    
                 SendMessage(hwndComboBox, CB_SETCURSEL, 0, 0);
    
                 hwndButton = CreateWindowEx(0, "BUTTON", "Değer değiştir", /* Buton oluşturma */
                                             WS_CHILD | WS_VISIBLE, 150, 20, 120, 24,
                                             hwnd, (HMENU) IDC_BUTTON, NULL, NULL);
                 break;
    
            case WM_COMMAND:
    
                 if (HIWORD(wParam) == BN_CLICKED) {
                     if (LOWORD(wParam) == IDC_BUTTON) {
                         ChangeComboBoxItem(); /* ComboBox seçili değerini değiştirme */
                     }
                 }
                 break;
    
            case WM_DESTROY:
                 PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
                 break;
            default:                        /* for messages that we don't deal with */
                 return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    
    void ChangeComboBoxItem(void)
    {
      int cbindex;
      char cdizi[20];
    
      strcpy(cdizi, "Yeni değer");
    
      cbindex = ComboBox_GetCurSel(hwndComboBox); /* ComboBox seçili eleman indeksini alma */
    
      ComboBox_DeleteString(hwndComboBox, cbindex); /* ComboBox seçili elemanı listeden silme */
      ComboBox_InsertString(hwndComboBox, cbindex, cdizi); /* ComboBox silinen eleman indeksine yeni bir eleman ekleme */
      ComboBox_SetCurSel(hwndComboBox, cbindex); /* ComboBox yeni elemanı seçme */
    }
    
    

    Programı derleyip çalıştırdığımızda, ComboBox kontrolünün herhangi bir elemanını seçer ve butona tıklarsak, seçtiğimiz eleman adı "Yeni değer" olarak değişir. Bu durumda, program aşağıdakine benzer bir görüntü oluşturacaktır: