Forum dyskusyjne  |  Kanał IRC | Użytkownicy | Hosting
Listview
załącznik
2006-02-01 17:24:00, wyświetleń: 5668 [ edycja ] | [ historia ]


Dzisiaj omówimy sobie jedną z ważniejszych kontrolek WinApi, jaką jest kontrolka ListView. Służy ona do wyświetlania informacji z możliwością przyporządkowania im ikon. Żeby móc używać niektórych opcji tej kontrolki, musimy posiadać bibliotekę ComCtl32.dll przynajmniej w wersji 6 (WinXP i następne). Wszystkie niżej wymienione funkcje znajdują się w pliku nagłówkowym commctrl.h. Najpierw najbardziej podstawowa rzecz, czyli utworzenie kontrolki:

Kod:
InitCommonControls();
listview=CreateWindow(WC_LISTVIEW,"",WS_VISIBLE|WS_CHILD,10,10,300,200,hwnd,0,GetModuleHandle(NULL),0)


Żeby zapewnić załadowanie odpowiedniej biblioteki do obsługi tej kontrolki, musimy na samym początku wywołać funkcję InitCommonControls.
Kontrolka ListView posiada 4 różne typy widoków wyświetlanych informacji i odpowiadające im flagi:
small icon view - LVS_SMALLICON, przy każdej pozycji, po lewej, jest wyświetlana mała ikona
icon view - LVS_ICON, przy każdej pozycji, wyświetlana jest ikona normalnych rozmiarów
list view - LVS_LIST, wyświetlana jest lista informacji, ikona jest po lewej
reported view - LVS_REPORT, widok kolumnowy, każda informacja jest umieszczona w oddzielnej linii, informacje w pierwszej kolumnie mogą posiadać ikonę, która wyświetlana jest po lewej, każda kolumna posiada nagłówek, ale można to zmienić, uwzględniając styl LVS_NOCOLUMNHEADER przy tworzeniu okna.

Jeżeli chcemy stworzyć kontrolkę z widokiem np. reported view, to musimy dołączyć odpowiednią flagę:

Kod:
listview=CreateWindow(WC_LISTVIEW,"",WS_VISIBLE|WS_CHILD|LVS_REPORT,10,10,300,200,hwnd,0,GetModuleHandle(NULL),0);


Możemy również używać rozszerzonych stylów, takich jak:
LVS_EX_CHECKBOXES - przy każdej informacji zostaje umieszczone pole checkbox
LVS_EX_FULLROWSELECT - cały rząd zostaje podświetlony przy zaznaczaniu pola
LVS_EX_FLATSB - zmienia scrollbary w kontrolce na płaskie
Żeby ustawić rozszerzony style kontrolki, używamy funkcji ListView_SetExtendedListViewStyle(uchwyt,styl):

Kod:
ListView_SetExtendedListViewStyle(listview,LVS_EX_CHECKBOXES) ;


My weźmiemy na warsztat widok LVS_REPORT, ponieważ jest najbardziej przydatny. A więc, przydało by się dodać parę kolumn. Służy do tego funkcja ListView_InsertColumn:

Kod:
void DodajKolumny(HWND h){
LVCOLUMN c;
c.mask=LVCF_TEXT|LVCF_WIDTH; // flagi
c.cx=100; // szerokość kolumny w pikselach
c.pszText="Kolumna 1"; // nagłówek
ListView_InsertColumn(h,0,&c); // dodajemy kolumnę
c.pszText="Kolumna 2"; // nagłówek
ListView_InsertColumn(h,1,&c); // dodajemy kolumnę
c.pszText="Kolumna 3"; // nagłówek
ListView_InsertColumn(h,2,&c); // dodajemy kolumnę
}


Teraz wystarczy tylko wywołać tą funkcję i mamy już gotowe kolumny:

Kod:
DodajKolumny(listview)


Kolumny mamy, więc dodamy teraz parę pozycji. Jak zwykle jest do tego gotowa funkcja ListView_InsertItem. Jako jeden z parametrów podajemy strukturę LVITEM. Przyjrzyjmy się jej trochę bliżej:

Kod:
typedef struct _LVITEM {
    UINT mask;
    int iItem;
    int iSubItem;
    UINT state;
    UINT stateMask;
    LPTSTR pszText;
    int cchTextMax;
    int iImage;
    LPARAM lParam;
#if (_WIN32_IE >= 0x0300)
    int iIndent;
#endif
#if (_WIN32_IE >= 0x560)
    int iGroupId;
    UINT cColumns; // tile view columns
    PUINT puColumns;
#endif
} LVITEM, *LPLVITEM;


Ta struktura służy również do pobierania informacji o danym polu, dlatego każde pole w zależności od kontekstu użycia musi być wypełnione (kiedy dodajemy pole) lub zostanie zwrócone (kiedy pobieramy informacje). A teraz po kolei parametry:
mask - flagi decydujące o tym, które pole muszą być wypełnione, lub które pola funkcja zwróci, może przyjmować, jedną lub więcej wartości:
LVIF_COLUMNS - pole cColums musi być wypełnione lub zostanie zwrócone
LVIF_GROUPID - pole iGroupId musi być wypełnione lub zostanie zwrócone
LVIF_IMAGE - pole iImage musi być wypełnione lub zostanie zwrócone
LVIF_INDENT - pole iIndent musi być wypełnione lub zostanie zwrócone
LVIF_PARAM - pole lParam musi być wypełnione lub zostanie zwrócone
LVIF_STATE - pole state musi być wypełnione lub zostanie zwrócone
LVIF_TEXT - pole pszText musi być wypełnione lub zostanie zwrócone
iItem - numer pola na którym operujemy
iSubItem - numer subitema na którym operujemy, jeżeli ustawimy wartość 0, to pole odnosi się do pozycji (informacji w pierwszej kolumnie)
state - wskazuje na stan pola
stateMask - informuje, o tym, które bity pola state mają być brane pod uwagę przy ustawianiu stanu pola
pszText - bufor z tekstem pola
cchTextMax rozmiar bufora
iImage - numer rysunku przypisanego do danego pola
lParam - wartość specyficzna dla każdego pola, używana przy sortowaniu pól
iIndent - pole to określa na ile szerokości obrazka przypisanego do danego pola wcięte będzie pole, standardowo 1

Dodajmy więc kilka pól do kontrolki. Stworzymy jedną funkcję, która będzie dodawała nowe pozycje, a potem wywołamy ją 5 razy:

Kod:
void DodajPozycje(HWND h,char*itemtext,char*subitem1,char*subitem2,int i)
{
LVITEM p;
ZeroMemory(&p,sizeof(p)); // czyścimy zmienną
p.mask=LVIF_TEXT|LVIF_PARAM; // tekst i informacje potrzebne do sortowania
p.lParam=(LPARAM)itemtext;       
p.iSubItem=0;
p.iItem=i; // numer pola
p.pszText=itemtext; // tekst pola
ListView_InsertItem(h,&p);

p.mask=LVIF_TEXT; // tekst
p.iItem=i;
p.iSubItem=1; // numer subitema
p.pszText=subitem1;
ListView_SetItem(h,&p); // ustawiamy pole z jednym subitemem

p.iItem=i;
p.iSubItem=2;
p.pszText=subitem2;
ListView_SetItem(h,&p); // ustawiamy pole z drugim subitemem
}

DodajPozycje(listview,"pozycja1","pozycja1 subitem1","pozycja1 subitem2",0);
DodajPozycje(listview,"pozycja2","pozycja2 subitem1","pozycja2 subitem2",1);       
DodajPozycje(listview,"pozycja3","pozycja3 subitem1","pozycja3 subitem2",2);       
DodajPozycje(listview,"pozycja4","pozycja4 subitem1","pozycja4 subitem2",3);               
DodajPozycje(listview,"pozycja5","pozycja5 subitem1","pozycja5 subitem2",4);


Poznamy teraz możliwości jakie stwarza dla nas WinApi w zakresie modyfikowania wyglądu kontrolki ListView. Aby zmienić kolor tekstu użyjemy funkcji SendMessage, podając jako komunikat LVM_SETTEXTCOLOR:

Kod:
SendMessage(listview,LVM_SETTEXTCOLOR,0,(LPARAM)(COLORREF)0xFFFFFF); // biały kolor


Do zmiany koloru tła tekstu i tła kontrolki służą odpowiednio komunikaty LVM_SETTEXTBKCOLOR i LVM_SETBKCOLOR:

Kod:
SendMessage(listview,LVM_SETBKCOLOR,0,(LPARAM)(COLORREF)0x000000);
SendMessage(listview,LVM_SETTEXTBKCOLOR,0,(LPARAM)(COLORREF)CLR_NONE);


Jeżeli chcemy, aby kolor był całkowicie przeźroczysty, podstawiamy pod kolor wartość CLR_NONE. Przydatną rzeczą może również okazać się możliwość podstawienia obrazka jako tło kontrolki:

Kod:
CoInitialize(NULL);
LVBKIMAGE h;
h.ulFlags=LVBKIF_SOURCE_URL|LVBKIF_STYLE_TILE;       
h.pszImage="d:\\rys.bmp";
h.xOffsetPercent=0;
h.yOffsetPercent=0;
SendMessage(listview,LVM_SETBKIMAGE,0,(LPARAM)&h);

case WM_CLOSE:
CoUninitialize();       
SendMessage(hwnd,WM_DESTROY,0,0);
break;


Powyższy kod ustawia jako tło kontrolki plik d:\rys.bmp i rysuje go kafelkowo. Jeżeli chcemy, aby obrazek został tylko raz narysowany zamiast flagi LVBKIF_STYLE_TILE podstawiamy flagę LVBKIF_STYLE_NORMAL. Ponieważ kontrolka ListView używa techniki OLE przy obsłudze tła, nasza aplikacja musi wywołać na początku funkcję CoInitialize, a na końcu funkcję CoUninitialize.

Omówimy na koniec jeszcze jedną ważną rzecz, a mianowicie sortowanie pól. Aby posortować pola musimy najpierw zdefiniować własną funkcję porównującą dwa elementy:

Kod:
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, 
        LPARAM lParamSort)
{
        return -strcmp((char*)lParam1,(char*)lParam2);
}


Funkcja strcmp porównuje dwa napisy z uwzględnieniem wielkości znaków i zwraca 0 gdy są napisy równe, 1 gdy napis pierwszy jest większy od drugiego lub -1 w przypadku gdy drugi napis jest większy od drugiego. My chcemy posortować pola w kierunku malejącym, więc musimy zmienić znak wyniku funkcji strcmp. Parametry lParam1 i lParam2 są to zdefiniowane przez nas informacje, które ustawiliśmy w polu lParam podczas dodawania nowych pozycji. Parametr lParamSort zawiera dodatkowe informacje przekazywane podczas wywoływania funkcji SendMessage:

Kod:
SendMessage(listview,LVM_SORTITEMS,(WPARAM)0/*dodatkowe informacje*/,(LPARAM)CompareFunc);


Jeżeli jest coś, co jeszcze chcecie wiedzieć, a ja o tym nie wspomniałem, piszcie na maila.


Pobierz załącznik załącznik

Autor: krajew4

Komentarze
Artykuły mogą być komentowane wyłącznie przez zarejestrowanych użytkowników.

Zaloguj się | Załóż nowe konto

2010-02-03 07:11:45

jak najszybciej
2010-01-10 05:25:20

Jak usunąć zaznaczoną pozycje z listview.
2009-08-06 04:33:21

A kto ma pisać, jak dorośli tego nie wiedzą ?
2009-08-04 20:35:28

Błędne nazewnictwo stosujesz.LVS_LIST, LVS_REPORT to nie flagi tylko style.ListView_InsertColumn to nie funkcja tylko makro.Dzieci pisza artykuly...
Redakcja zastrzega sobie prawo do skracania, usuwania komentarzy o treściach wulgarnych, obraźliwych oraz niezgodnych z polskim i miedzynarodowym prawem. Unit1.pl Team nie ponosi odpowiedzialności za treść komentarza.