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

Ana page > Programlama > Windows API Programlama > Tab

Tab

► Kontroller

Windows API ile bir tab kontrolü oluşturmak için CreateWindowEx() fonksiyonunun ikinci parametresinde WC_TABCONTROL değerini kullanmamız gerekir. Bu ifadenin tanımı da commctrl.h başlık dosyasında yer aldığından bu dosya programımıza dahil edilmelidir.

Ancak, Tab kontrolü altında oluşturulan öğeler bir pencere niteliği taşımadığından, Tab kontrolü öğeleri altına herhangi bir kontrol veya veri yerleştirilememektedir. Bu nedenle, Tab kontrolünün öğeleri seçildiğinde her öğe için ekranda gösterilecek kontrol ve verileri Tab kontrolü altında her öğe için özel bir sınıf yoluyla oluşturulan Panellere yerleştirerek işlem yapmaya çalışacağız. Tab kontrolü öğelerinden birine tıkladığımızda sadece o öğeye ait Panel ekranda gösterilecek diğer paneller gizlenecektir.

Dosya başlık bilgilerini oluşturma

1. Öncelikle Burada gösterildiği gibi bir Windows API projesi oluşturalım. Projeyle birlikte otomatik olarak oluşturulan main.c dosyasının başlangıç kısmını aşağıdaki şekilde düzenleyelim:


#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif

#define IDC_PANELTAB01 101
#define IDC_PANELTAB02 102
#define IDC_PANELTAB03 103
#define IDC_BUTTON01 104
#define IDC_BUTTON02 105
#define IDC_BUTTON03 106

#include <tchar.h>
#include <windows.h>
#include <commctrl.h>

/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Fonksiyon bildirimleri */
void CreateTabControl (HWND hwndMain);
void CreateTabPanels (void);
void CreatePanelButtons (void);
LRESULT CALLBACK PanelTabProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void ShowTabWindow(int TabWin);

/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");

HWND hwndTab;
HWND hwndPanelTab01, hwndPanelTab02, hwndPanelTab03;
HWND hwndButton01, hwndButton02, hwndButton03;

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)

Aşağıdaki satır ile commctrl.h başlık dosyası ile Tab kontrolü oluşturma ile ilgili fonksiyonların ve değerlerin kullanımı sağlanır.


#include <commctrl.h>

Aşağıdaki satır ile Tab kontrolü içinde oluşturulacak paneller için kullanılacak PanelProc() fonksiyonunun tanımlaması programa eklenir.


LRESULT CALLBACK PanelProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

Aşağıdaki satırlar ile bir adet tab kontrolü, 3 adet panel ve 3 adet buton pencere değeri programa eklenir.


HWND hwndTab;
HWND hwndPanelTab01, hwndPanelTab02, hwndPanelTab03;
HWND hwndButton01, hwndButton02, hwndButton03;

Windows Procedure düzenleme

WindowProcedure içinde oluşturacağımız WM_CREATE ve WM_NOTIFY seçeneklerine aşağıdaki satırları ekleyelim:


LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) {
        case WM_CREATE:
             /* Tab kontrolü oluşturma */
             CreateTabControl(hwnd);
             /* Tab kontrolü içinde panelleri oluşturma */
             CreateTabPanels();
             /* Tab kontrolü panelleri içinde buton kontrolleri oluşturma */
             CreatePanelButtons();
             break;

        case WM_NOTIFY:
           {
             switch (((LPNMHDR)lParam)->code) {
                 case TCN_SELCHANGE: /* Tab kontrolü sayfa seçimi */
                 {
                   int iTab = TabCtrl_GetCurSel(hwndTab);

                   if (((LPNMHDR)lParam)->hwndFrom == hwndTab) {
                       ShowTabWindow(iTab); /* Seçilen sayfada yer alan paneli gösterme */
                   }
                   break;
                 }
             }
             break;
           }

Tab kontrolü oluşturma

Ana pencere içinde Tab kontrolünü oluşturacak fonksiyonu programa ekleyelim:


void CreateTabControl (HWND hwndMain)
{
  TCITEM tie;
  RECT rc;
  char cd[3][10] = { "Tab01", "Tab02", "Tab03" };
  int id1;

  GetClientRect(hwndMain, &rc);

  /* Tab kontrolü oluşturma */
  hwndTab = CreateWindowEx(0, WC_TABCONTROL, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
                              0, 0, rc.right, rc.bottom, hwndMain, 0, NULL, NULL);

  tie.mask = TCIF_TEXT | TCIF_IMAGE;
  tie.iImage = -1;

  for (id1=0; id1<3; id1++) {
       tie.pszText = cd[id1];
       /* Tab kontrolü item'larını oluşturma */
       if (TabCtrl_InsertItem(hwndTab, id1, &tie) == -1) {
           DestroyWindow(hwndTab);
           return;
       }
  }
}

Tab kontrolü içindeki panelleri oluşturma

Aşağıdaki satırları programa ekleyelim:


void CreateTabPanels (void)
{
  WNDCLASSEX winpan = {0};
  RECT rc;

  winpan.cbSize = sizeof (WNDCLASSEX);
  winpan.lpszClassName = TEXT("PanelTab");
  winpan.lpfnWndProc = PanelTabProc; /* Sınıf için fonksiyon atama */
  winpan.hCursor = LoadCursor (NULL, IDC_ARROW);
  winpan.cbClsExtra = 0;
  winpan.cbWndExtra = 0;
  winpan.hbrBackground = GetSysColorBrush(COLOR_3DFACE);

  if (!RegisterClassEx (&winpan)) return;

  GetClientRect(hwndTab, &rc);

  /* Tab panellerini oluşturma */
  hwndPanelTab01 = CreateWindowEx (0, winpan.lpszClassName, NULL,
                  WS_CHILD | WS_VISIBLE, 5, 25, (rc.right-rc.left)-10, (rc.bottom-rc.top)-30,
                  hwndTab, (HMENU) IDC_PANELTAB01, 0, NULL);

  hwndPanelTab02 = CreateWindowEx (0, winpan.lpszClassName, NULL,
                  WS_CHILD | WS_VISIBLE, 5, 25, (rc.right-rc.left)-10, (rc.bottom-rc.top)-30,
                  hwndTab, (HMENU) IDC_PANELTAB02, 0, NULL);

  hwndPanelTab03 = CreateWindowEx (0, winpan.lpszClassName, NULL,
                  WS_CHILD | WS_VISIBLE, 5, 25, (rc.right-rc.left)-10, (rc.bottom-rc.top)-30,
                  hwndTab, (HMENU) IDC_PANELTAB03, 0, NULL);

  /* İlk panel dışındaki panelleri gizleme */
  ShowWindow(hwndPanelTab02, SW_HIDE);
  ShowWindow(hwndPanelTab03, SW_HIDE);
}

LRESULT CALLBACK PanelTabProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message) {
     case WM_COMMAND:

          switch(HIWORD(wParam)) {
            case BN_CLICKED:
                 switch(LOWORD(wParam)) {
                    case IDC_BUTTON01:
                         MessageBox(NULL, "Buton01 tıklandı", "Mesaj", MB_OK);
                         break;
                    case IDC_BUTTON02:
                         MessageBox(NULL, "Buton02 tıklandı", "Mesaj", MB_OK);
                         break;
                    case IDC_BUTTON03:
                         MessageBox(NULL, "Buton03 tıklandı", "Mesaj", MB_OK);
                         break;
                 }
                 break;
          }
  }

CreateTabPanels() fonksiyonu ile Tab kontrolü içinde her bir öğe için bir adet olmak üzere 3 adet Panel oluşturulur. Paneller oluşturulurken PanelTabProc() fonksiyonu panel sınıfına atanır.

Paneller içinde Buton kontrolleri oluşturma

Aşağıdaki satırları programa ekleyelim:


void CreatePanelButtons (void)
{
  hwndButton01 = CreateWindowEx(0, "BUTTON", "Button01",
                 WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 30, 120, 25,
                 hwndPanelTab01, (HMENU) IDC_BUTTON01, NULL, NULL);

  hwndButton02 = CreateWindowEx(0, "BUTTON", "Button02",
                 WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 30, 120, 25,
                 hwndPanelTab02, (HMENU) IDC_BUTTON02, NULL, NULL);

  hwndButton03 = CreateWindowEx(0, "BUTTON", "Button03",
                 WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 30, 120, 25,
                 hwndPanelTab03, (HMENU) IDC_BUTTON03, NULL, NULL);
}

CreatePanelButtons() fonksiyonu ile her panel içinde bir adet olmak üzere 3 adet Buton oluşturulur.

Tab kontrolü öğe değiştirme fonksiyonu oluşturma

Aşağıdaki satırları programa ekleyelim:


void ShowTabWindow(int TabWin)
{
  TabCtrl_SetCurSel(hwndTab, TabWin);

  switch (TabWin) {
     case 0:
        ShowWindow(hwndPanelTab01, SW_SHOW);
        ShowWindow(hwndPanelTab02, SW_HIDE);
        ShowWindow(hwndPanelTab03, SW_HIDE);
        break;
     case 1:
        ShowWindow(hwndPanelTab01, SW_HIDE);
        ShowWindow(hwndPanelTab02, SW_SHOW);
        ShowWindow(hwndPanelTab03, SW_HIDE);
        break;
     case 2:
        ShowWindow(hwndPanelTab01, SW_HIDE);
        ShowWindow(hwndPanelTab02, SW_HIDE);
        ShowWindow(hwndPanelTab03, SW_SHOW);
        break;
  }
}

WindowProcedure fonksiyonunda, WM_NOTIFY seçeneği içinde TCN_SELCHANGE mesaj parametresi ile elde edilen Tab kontrolünde seçilen öğenin indeks değeri kullanılarak ShowTabWindow() fonksiyonu çağrılır. Geçirilen değere göre Tab kontrolü altında oluşturulan panellerden sadece birisi ekranda gösterilir. Diğerleri ise gizlenir.

Kodların son hali (main.c dosyası)

Yukarıdaki kodları 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_PANELTAB01 101
#define IDC_PANELTAB02 102
#define IDC_PANELTAB03 103
#define IDC_BUTTON01 104
#define IDC_BUTTON02 105
#define IDC_BUTTON03 106

#include <tchar.h>
#include <windows.h>
#include <commctrl.h>

/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Fonksiyon bildirimleri */
void CreateTabControl (HWND hwndMain);
void CreateTabPanels (void);
void CreatePanelButtons (void);
LRESULT CALLBACK PanelTabProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
void ShowTabWindow(int TabWin);

/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");

HWND hwndTab;
HWND hwndPanelTab01, hwndPanelTab02, hwndPanelTab03;
HWND hwndButton01, hwndButton02, hwndButton03;

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("Tab kontrolü oluşturma"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           385,                 /* 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) {
        case WM_CREATE:
             /* Tab kontrolü oluşturma */
             CreateTabControl(hwnd);
             /* Tab kontrolü içinde panelleri oluşturma */
             CreateTabPanels();
             /* Tab kontrolü panelleri içinde buton kontrolleri oluşturma */
             CreatePanelButtons();
             break;

        case WM_NOTIFY:
           {
             switch (((LPNMHDR)lParam)->code) {
                 case TCN_SELCHANGE: /* Tab kontrolü sayfa seçimi */
                 {
                   int iTab = TabCtrl_GetCurSel(hwndTab);

                   if (((LPNMHDR)lParam)->hwndFrom == hwndTab) {
                       ShowTabWindow(iTab); /* Seçilen sayfada yer alan paneli gösterme */
                   }
                   break;
                 }
             }
             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 CreateTabControl (HWND hwndMain)
{
  TCITEM tie;
  RECT rc;
  char cd[3][10] = { "Tab01", "Tab02", "Tab03" };
  int id1;

  GetClientRect(hwndMain, &rc);

  /* Tab kontrolü oluşturma */
  hwndTab = CreateWindowEx(0, WC_TABCONTROL, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
                              0, 0, rc.right, rc.bottom, hwndMain, 0, NULL, NULL);

  tie.mask = TCIF_TEXT | TCIF_IMAGE;
  tie.iImage = -1;

  for (id1=0; id1<3; id1++) {
       tie.pszText = cd[id1];
       /* Tab kontrolü item'larını oluşturma */
       if (TabCtrl_InsertItem(hwndTab, id1, &tie) == -1) {
           DestroyWindow(hwndTab);
           return;
       }
  }
}

void CreateTabPanels (void)
{
  WNDCLASSEX winpan = {0};
  RECT rc;

  winpan.cbSize = sizeof (WNDCLASSEX);
  winpan.lpszClassName = TEXT("PanelTab");
  winpan.lpfnWndProc = PanelTabProc; /* Sınıf için fonksiyon atama */
  winpan.hCursor = LoadCursor (NULL, IDC_ARROW);
  winpan.cbClsExtra = 0;
  winpan.cbWndExtra = 0;
  winpan.hbrBackground = GetSysColorBrush(COLOR_3DFACE);

  if (!RegisterClassEx (&winpan)) return;

  GetClientRect(hwndTab, &rc);

  /* Tab panellerini oluşturma */
  hwndPanelTab01 = CreateWindowEx (0, winpan.lpszClassName, NULL,
                  WS_CHILD | WS_VISIBLE, 5, 25, (rc.right-rc.left)-10, (rc.bottom-rc.top)-30,
                  hwndTab, (HMENU) IDC_PANELTAB01, 0, NULL);

  hwndPanelTab02 = CreateWindowEx (0, winpan.lpszClassName, NULL,
                  WS_CHILD | WS_VISIBLE, 5, 25, (rc.right-rc.left)-10, (rc.bottom-rc.top)-30,
                  hwndTab, (HMENU) IDC_PANELTAB02, 0, NULL);

  hwndPanelTab03 = CreateWindowEx (0, winpan.lpszClassName, NULL,
                  WS_CHILD | WS_VISIBLE, 5, 25, (rc.right-rc.left)-10, (rc.bottom-rc.top)-30,
                  hwndTab, (HMENU) IDC_PANELTAB03, 0, NULL);

  /* İlk panel dışındaki panelleri gizleme */
  ShowWindow(hwndPanelTab02, SW_HIDE);
  ShowWindow(hwndPanelTab03, SW_HIDE);
}

void CreatePanelButtons (void)
{
  hwndButton01 = CreateWindowEx(0, "BUTTON", "Button01",
                 WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 30, 120, 25,
                 hwndPanelTab01, (HMENU) IDC_BUTTON01, NULL, NULL);

  hwndButton02 = CreateWindowEx(0, "BUTTON", "Button02",
                 WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 30, 120, 25,
                 hwndPanelTab02, (HMENU) IDC_BUTTON02, NULL, NULL);

  hwndButton03 = CreateWindowEx(0, "BUTTON", "Button03",
                 WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 30, 120, 25,
                 hwndPanelTab03, (HMENU) IDC_BUTTON03, NULL, NULL);
}

/* Panel fonksiyonu */
LRESULT CALLBACK PanelTabProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message) {
     case WM_COMMAND:

          switch(HIWORD(wParam)) {
            case BN_CLICKED:
                 switch(LOWORD(wParam)) {
                    case IDC_BUTTON01:
                         MessageBox(NULL, "Buton01 tıklandı", "Mesaj", MB_OK);
                         break;
                    case IDC_BUTTON02:
                         MessageBox(NULL, "Buton02 tıklandı", "Mesaj", MB_OK);
                         break;
                    case IDC_BUTTON03:
                         MessageBox(NULL, "Buton03 tıklandı", "Mesaj", MB_OK);
                         break;
                 }
                 break;
          }
  }

  return DefWindowProc (hwnd, message, wParam, lParam);
}

void ShowTabWindow(int TabWin)
{
  TabCtrl_SetCurSel(hwndTab, TabWin);

  switch (TabWin) {
     case 0:
        ShowWindow(hwndPanelTab01, SW_SHOW);
        ShowWindow(hwndPanelTab02, SW_HIDE);
        ShowWindow(hwndPanelTab03, SW_HIDE);
        break;
     case 1:
        ShowWindow(hwndPanelTab01, SW_HIDE);
        ShowWindow(hwndPanelTab02, SW_SHOW);
        ShowWindow(hwndPanelTab03, SW_HIDE);
        break;
     case 2:
        ShowWindow(hwndPanelTab01, SW_HIDE);
        ShowWindow(hwndPanelTab02, SW_HIDE);
        ShowWindow(hwndPanelTab03, SW_SHOW);
        break;
  }
}

Program derleyip çalıştırdığımızda aşağıdakine benzer bir ekran görüntüsü karşımıza gelecektir. Tab kontrolünün her sekmesine tıkladığımızda o sekmeye ait panel ekranda gösterilecektir.

Proje dosyaları ve .exe dosya

Programın kaynak kodları

Programın exe dosyası