Windows API

Panel Kontrolü

► Kontroller

Windows API ile kullanılmak üzere sistem tarafından önceden tanımlanmış bir panel kontrolü yoktur. Statik kontrol kullanarak veya yeni bir Windows sınıfı tanımlayarak bir panel kontrolü oluşturabiliriz.

Panel kontrolünü statik kontrol yoluyla 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 _WIN32_WINNT 0x0501
#define _WIN32_IE 0x0501

#define IDC_PANEL 101
#define IDC_BUTTON 102

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

/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Panel için fonksiyon */
LRESULT CALLBACK PanelProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);

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

HWND hwndPanel, hwndButton;

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

Programa eklenen aşağıdaki satırlar ile, XP ve daha sonraki işletim sistemlerinde eklenen SetWindowSubclass ve DefSubclassProc fonksiyonları ile bazı değişkenlerin kullanımı sağlanır. Bu satırlar kaldırıldığında, program derleme hatası verir.

#define _WIN32_WINNT 0x0501
#define _WIN32_IE 0x0501

Aşağıdaki satır ile commctrl.h başlık dosyası ile SetWindowSubclass ve DefSubclassProc fonksiyonlarının kullanımı sağlanır.

#include <commctrl.h>

Aşağıdaki satır ile Subclass yönteminde kullanılacak PanelProc() fonksiyonu tanımlaması programa eklenir.

LRESULT CALLBACK PanelProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);

Aşağıdaki satır ile bir adet panel ve bir adet buton pencere değeri programa eklenir.

HWND hwndPanel, hwndButton;

2. Şimdi, statik bir panel ve bir buton oluşturmak ve panele bir fonksiyon atamak için;

WindowProcedure içinde oluşturacağımız WM_CREATE seçeneğine aşağıdaki satırları ekleyelim:

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

             /* Panel için statik bir kontrol oluşturma */
             hwndPanel = CreateWindowEx(0, "STATIC", "",
                            WS_CHILD | WS_VISIBLE, 20, 20, 300, 200,
                            hwnd, (HMENU) IDC_PANEL, NULL, NULL);

             /* Panel için fonksiyon atama */
             SetWindowSubclass(hwndPanel, PanelProc, 0, 0);

             /* Panel içinde buton oluşturma */
             hwndButton = CreateWindowEx(0, "BUTTON", "Button",
                             WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 20, 120, 25,
                             hwndPanel, (HMENU) IDC_BUTTON, NULL, NULL);
             break;

3. Panel arka plan rengini belirlemek için;

WindowProcedure içinde oluşturacağımız WM_CTLCOLORSTATIC seçeneğine aşağıdaki satırları ekleyelim:

case WM_CTLCOLORSTATIC:
     /* Panel arka plan rengini ayarlama */
     return (INT_PTR) (HBRUSH) CreateSolidBrush (RGB(144, 210, 30));
     break;

4. Panel için atadığımız fonksiyonu oluşturmak için;

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

LRESULT CALLBACK PanelProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
  switch (message) {
     case WM_COMMAND:

         switch(HIWORD(wParam)) {
            case BN_CLICKED:
                 if (LOWORD(wParam)==IDC_BUTTON) {
                     MessageBox(NULL, "Butona tıklandı", "Mesaj", MB_OK);
                 }
                 break;
         }
   }

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

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 _WIN32_WINNT 0x0501
#define _WIN32_IE 0x0501

#define IDC_PANEL 101
#define IDC_BUTTON 102

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

/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Panel için fonksiyon */
LRESULT CALLBACK PanelProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);

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

HWND hwndPanel, hwndButton;

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("Panel 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:

             /* Panel için statik bir kontrol oluşturma */
             hwndPanel = CreateWindowEx(0, "STATIC", "",
                            WS_CHILD | WS_VISIBLE, 20, 20, 300, 200,
                            hwnd, (HMENU) IDC_PANEL, NULL, NULL);

             /* Panel için fonksiyon atama */
             SetWindowSubclass(hwndPanel, PanelProc, 0, 0);

             /* Panel içinde buton oluşturma */
             hwndButton = CreateWindowEx(0, "BUTTON", "Button",
                             WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 20, 120, 25,
                             hwndPanel, (HMENU) IDC_BUTTON, NULL, NULL);
             break;

        case WM_CTLCOLORSTATIC:
             /* Panel arka plan rengini ayarlama */
             return (INT_PTR) (HBRUSH) CreateSolidBrush (RGB(144, 210, 30));
             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;
}

LRESULT CALLBACK PanelProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
  switch (message) {
     case WM_COMMAND:

         switch(HIWORD(wParam)) {
            case BN_CLICKED:
                 if (LOWORD(wParam)==IDC_BUTTON) {
                     MessageBox(NULL, "Butona tıklandı", "Mesaj", MB_OK);
                 }
                 break;
         }
  }

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

Program derleyip çalıştırdığımızda aşağıdakine benzer bir ekran görüntüsü karşımıza gelecektir:

Programın kaynak kodları

Programın exe dosyası

Panel kontrolünü yeni bir Windows sınıfı tanımlayarak 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_PANEL 101
#define IDC_BUTTON 102

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

/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Panel oluşturma fonksiyonu bildirimi */
HWND CreatePanel (HWND hwnd);
/* Panel için fonksiyon */
LRESULT CALLBACK PanelProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

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

HWND hwndPanel, hwndButton;

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

Programa eklenen aşağıdaki satır ile panel oluşturmak için kullanacağımız fonksiyonun bildirimi yapılır.

HWND CreatePanel (HWND hwnd);

Aşağıdaki satır ile yeni bir Windows sınıfı tanımlayarak oluşturacağımız Panel kontrolüne atayacağımız PanelProc() fonksiyonunun tanımlaması programa eklenir.

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

Aşağıdaki satır ile bir adet panel ve bir adet buton pencere değeri programa eklenir.

HWND hwndPanel, hwndButton;

2. Şimdi, bir panel ve panelin içinde bir buton oluşturmak için;

WindowProcedure içinde oluşturacağımız WM_CREATE seçeneğine aşağıdaki satırları ekleyelim:

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

             /* Windows sınıfı oluşturup kaydederek panel oluşturma */
             hwndPanel = CreatePanel(hwnd);

             /* Panel içinde buton oluşturma */
             hwndButton = CreateWindowEx(0, "BUTTON", "Button",
                             WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 20, 120, 25,
                             hwndPanel, (HMENU) IDC_BUTTON, NULL, NULL);

             break;

3. Paneli oluşturan fonksiyonu programa eklemek için;

main.c dosyasının sonuna aşağıdaki satırları ekleyelim:

HWND CreatePanel (HWND hwnd)
{
  WNDCLASSEX winpan = {0};
  HWND hwndPanel;

  winpan.cbSize = sizeof (WNDCLASSEX);
  winpan.lpszClassName = TEXT("Panel");
  winpan.lpfnWndProc = PanelProc;
  winpan.hCursor = LoadCursor (NULL, IDC_ARROW);
  winpan.cbClsExtra = 0;
  winpan.cbWndExtra = 0;
  winpan.hbrBackground = (HBRUSH) CreateSolidBrush (RGB(200, 230, 255));

  if (!RegisterClassEx (&winpan)) return 0;

  hwndPanel = CreateWindowEx (0, winpan.lpszClassName, NULL,
                  WS_CHILD | WS_VISIBLE, 20, 20, 300, 200,
                  hwnd, (HMENU) IDC_PANEL, 0, NULL);

  return hwndPanel;
}

4. Panel için atadığımız fonksiyonu oluşturmak için;

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

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

          switch(HIWORD(wParam)) {
            case BN_CLICKED:
                 if (LOWORD(wParam)==IDC_BUTTON) {
                     MessageBox(NULL, "Butona tıklandı", "Mesaj", MB_OK);
                 }
                 break;
          }
  }

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

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_PANEL 101
#define IDC_BUTTON 102

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

/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Panel oluşturma fonksiyonu bildirimi */
HWND CreatePanel (HWND hwnd);
/* Panel için fonksiyon */
LRESULT CALLBACK PanelProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

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

HWND hwndPanel, hwndButton;

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("Panel 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:

             /* Windows sınıfı oluşturup kaydederek panel oluşturma */
             hwndPanel = CreatePanel(hwnd);

             /* Panel içinde buton oluşturma */
             hwndButton = CreateWindowEx(0, "BUTTON", "Button",
                             WS_CHILD | WS_VISIBLE | BS_NOTIFY, 20, 20, 120, 25,
                             hwndPanel, (HMENU) IDC_BUTTON, NULL, NULL);

             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;
}

HWND CreatePanel (HWND hwnd)
{
  WNDCLASSEX winpan = {0};
  HWND hwndPanel;

  winpan.cbSize = sizeof (WNDCLASSEX);
  winpan.lpszClassName = TEXT("Panel");
  winpan.lpfnWndProc = PanelProc;
  winpan.hCursor = LoadCursor (NULL, IDC_ARROW);
  winpan.cbClsExtra = 0;
  winpan.cbWndExtra = 0;
  winpan.hbrBackground = (HBRUSH) CreateSolidBrush (RGB(200, 230, 255));

  if (!RegisterClassEx (&winpan)) return 0;

  hwndPanel = CreateWindowEx (0, winpan.lpszClassName, NULL,
                  WS_CHILD | WS_VISIBLE, 20, 20, 300, 200,
                  hwnd, (HMENU) IDC_PANEL, 0, NULL);

  return hwndPanel;
}

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

          switch(HIWORD(wParam)) {
            case BN_CLICKED:
                 if (LOWORD(wParam)==IDC_BUTTON) {
                     MessageBox(NULL, "Butona tıklandı", "Mesaj", MB_OK);
                 }
                 break;
          }
  }

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

Program derleyip çalıştırdığımızda aşağıdakine benzer bir ekran görüntüsü karşımıza gelecektir:

Programın kaynak kodları

Programın exe dosyası