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

Ana page > Programlama > Windows API Programlama > WinAPI örnek kodlar > winapi_ornek00007

Windows API örnek kodlar

Satır yüksekliği değişken ListView (Subclassing işlemi ile)

Bir Windows API programında kullanılan ListView kontrolünün satır (item) yüksekliğini değiştirmek için, ListView kontrolünü LVS_OWNERDRAWFIXED özelliği ile tanımlayıp, ListView kontrolünün içinde bulunduğu pencerenin fonksiyonunda WM_MEASUREITEM mesajına işlem yapabiliriz.

Programda yer alacak main.c dosyasının içeriği aşağıdaki şekilde olacaktır:

main.c


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

// commctrl.h içindeki bazı verilerin kullanımı için gerekli
#define _WIN32_WINNT 0x0601
#define _WIN32_IE 0x0501

#define IDC_LISTVIEWOWNER 1001

#define RENKSUTUN01 RGB(240,230,140)
#define RENKSUTUN02 RGB(229,223,107)
#define SELECTBG RGB(190,240,60)
#define SELECTFONT RGB(255,255,255)
#define RENKFONT RGB(50,50,50)

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

HWND ListViewOwner;

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
void FillListView(HWND hwnd);
LRESULT CALLBACK ListViewProc (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");

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("Satır yüksekliği değiştirilmiş Listview"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           440,                 /* The programs width */
           330,                 /* 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:
        {
             ListViewOwner = CreateWindowEx(WS_EX_CLIENTEDGE , WC_LISTVIEW, "",
                                  WS_CHILD | LVS_REPORT | WS_VISIBLE | LVS_OWNERDRAWFIXED,
                                  10, 10, 400, 265, hwnd,
                                  (HMENU)IDC_LISTVIEWOWNER, NULL, NULL);
             ListView_SetExtendedListViewStyle(ListViewOwner, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
             SetWindowSubclass(ListViewOwner, ListViewProc, 0, 0);
             FillListView(ListViewOwner);

             break;
        }

        case WM_DRAWITEM:
        {
             // ListView Item satır çizimi burada (Üst pencere WM_DRAWITEM)
             if (wParam == IDC_LISTVIEWOWNER) {
                 LPDRAWITEMSTRUCT lDraw = (LPDRAWITEMSTRUCT)lParam;
                 char cdizi[20];
                 int id1, id2;

                 // Eğer satır seçilmiş ise tüm satır seçim çizimi yapar.
                 if(lDraw->itemState && ODS_SELECTED) {
                    FillRect(lDraw->hDC, &lDraw->rcItem, CreateSolidBrush((COLORREF)SELECTBG));
                    SetTextColor (lDraw->hDC, SELECTFONT);
                 }
                 else {
                    FillRect(lDraw->hDC, &lDraw->rcItem, CreateSolidBrush((COLORREF)RGB(255,255,255)));
                    SetTextColor (lDraw->hDC, RENKFONT);
                 }
                 // Bir satırda yer alan öğe ve alt öğeleri sırayla çizme
                 for (id1=0, id2=5; id1<4; id1++, id2+=98) {
                      ListView_GetItemText(ListViewOwner, lDraw->itemID, id1, cdizi, sizeof(cdizi));
                      lDraw->rcItem.left=id2;
                      DrawText(lDraw->hDC, cdizi, strlen(cdizi), &lDraw->rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
                 }
             }

             break;
        }

        case WM_MEASUREITEM:
        {
             // ListView LVS_OWNERDRAWFIXED Özelliği ile tanımlandığında sadece bir kez çağrılır.
             // LVS_OWNERDRAWFIXED kullanılınca, NM_CUSTOMDRAW altındaki satır çizimi devre dışı kalır.
             LPMEASUREITEMSTRUCT mItem = (LPMEASUREITEMSTRUCT)lParam;
             if (mItem->CtlType==ODT_LISTVIEW) {
                 mItem->itemHeight = 24;
             }
             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 ListViewProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
  switch (message) {
     // LVS_OWNERDRAWFIXED ListView Header bölümünü çizmek için
     // Listview item satır çizimi üst pencere WM_DRAWITEM mesajı içinde
     case WM_DRAWITEM:
     {
          LPDRAWITEMSTRUCT lDraw = (LPDRAWITEMSTRUCT)lParam;
          char cdizi[20];
          HDITEM hdi = { 0 };
          hdi.mask = HDI_TEXT | HDI_FORMAT;
          hdi.pszText = cdizi;
          hdi.cchTextMax = 20;
          HBRUSH hBrush;

          if(lDraw->CtlType==ODT_HEADER) {
             SetBkMode(lDraw->hDC, TRANSPARENT);
             if (lDraw->itemID%2) hBrush = CreateSolidBrush(RENKSUTUN02);
             else hBrush = CreateSolidBrush(RENKSUTUN01);

             SetTextColor(lDraw->hDC, RENKFONT);
             SelectObject(lDraw->hDC, hBrush);

             FillRect(lDraw->hDC, &lDraw->rcItem, NULL);

             Header_GetItem(lDraw->hwndItem, lDraw->itemID, &hdi);
             DrawText(lDraw->hDC, cdizi, strlen(cdizi), &lDraw->rcItem, DT_CENTER|DT_VCENTER);
          }
          DeleteObject(hBrush);

          break;
     }
  }

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

void FillListView(HWND hwnd)
{
  LVCOLUMN lvc;
  LVITEM lvI;
  int idCol=4, idItem=10;
  char cdizi[15];
  int id1, id2;
  HDITEM hdi = { 0 };

  // LVCOLUMN structure için ilk değer atama işlemlerini yapar.
  lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  lvc.cx = 98;           // Sütun genişliği değeri
  lvc.pszText = cdizi;
  lvc.cchTextMax = sizeof(cdizi);
  lvc.fmt = LVCFMT_LEFT; // Sütunları sol tarafa ayarlar

  // Sütun ekleme işlemleri
  for (id1=0; id1<idCol; id1++) {
       lvc.iSubItem = id1;
       sprintf(cdizi, "%s%d", "Column", id1+1);
       lvc.pszText = cdizi;
       // Sütun ekleme işlemi
       ListView_InsertColumn(hwnd, id1, &a;lvc);
  }

  // Bu işlem yapılmazsa, Subclassing fonksiyonu (ListViewProc) içinde başlık değerlerine işlem yapılamaz.
  if (GetWindowLongPtr(hwnd, GWL_STYLE) & LVS_OWNERDRAWFIXED) {
      for (id1=0; id1<idCol; id1++) {
           hdi.mask = HDI_FORMAT;
           hdi.fmt = HDF_OWNERDRAW;
           Header_SetItem(ListView_GetHeader(hwnd), id1, &hdi);
      }
  }

  // LVITEM structure için ilk değer atama işlemlerini yapar.
  lvI.mask      = LVIF_TEXT | LVIF_STATE;
  lvI.stateMask = 0;
  lvI.iSubItem  = 0;
  lvI.state     = 0;

  // Satır ekleme işlemleri
  for (id1=0; id1<idItem; id1++) {
       lvI.iItem  = id1;
       sprintf(cdizi, "%s%d", "Item", id1+1);
       lvI.pszText   = cdizi;
       // İlk sütun için öğe ekleme işlemleri
       ListView_InsertItem(hwnd, &lvI);

       // Diğer sütunlar için öğe ekleme işlemleri
       for (id2=1; id2<idCol; id2++) {
            sprintf(cdizi, "%s%d-%d", "SubItem", id1+1, id2+1);
            ListView_SetItemText(hwnd, id1, id2, cdizi);
       }
  }
}

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ı