to jest przeca proste, robisz sobie strzałki (up, down i brak) w jednej bitmapie, ładujesz je ImageList_LoadImage(), ustawiasz imagelist headera listview HDM_SETIMAGELIST, dodajesz jakieś kolumny ze stylem LVCFMT_COL_HAS_IMAGES i ustawiasz początkową strzałkę.
hImageList = ImageList_LoadImage(_hInstance, IDB_BITMAP3, 16, 1, rgb(255,0,255), IMAGE_BITMAP, LR_LOADTRANSPARENT)
hControl = SendDlgItemMessage(hwndDlg, IDC_LIST1, LVM_GETHEADER, 0, 0)
SendMessage(hControl, HDM_SETIMAGELIST, 0, hImageList)
LVCOLUMN lvc
char txt[32]
int column
hControl = GetDlgItem(hwndDlg, IDC_LIST1)
lvc.mask = LVCF_FMT | LVCF_IMAGE | LVCF_TEXT | LVCF_WIDTH
lvc.fmt = LVCFMT_LEFT | LVCFMT_COL_HAS_IMAGES | LVCFMT_BITMAP_ON_RIGHT
lvc.cx = 70
lvc.pszText = &txt
for (column=0; column<6;column++)
{
wsprintf(txt, "col %d", column+1)
lvc.iImage = 2 /*no image*/
SendMessage(hControl, LVM_INSERTCOLUMN, column, &lvc)
}
//teraz potrzebujesz zapamiętać kilka zmiennych:
// - iLastClickedCol - zapamiętuje ostatnią klikniętą kolumnę
// - bSortAscending - sortuj rosnąco/malejąco (TRUE/FALSE)
// - hImageList - musisz to usunąć przy zamykaniu programu :)
SetProp(hControl, "iLastClickedCol", 0)
SetProp(hControl, "bSortAscending", FALSE)
SetProp(hControl, "hSortImageList", hImageList)
// w WM_NOTIFY sprawdzasz czy to jest listview i czy code=LVN_COLUMNCLICK
iLastClickedColumn = GetProp(hControl, "iLastClickedCol")
bSortAscending = GetProp(hControl, "bSortAscending")
iClickedColumn = *<NMLISTVIEW>lParam.iSubItem
lvc.mask = LVCF_IMAGE
//jeśli stara kolumna != nowa kolumna to
// usuwasz strzałkę ze starej kolumny i
// ustawiasz sortowanie na rosnące
if (iClickedColumn != iLastClickedColumn)
{
lvc.iImage = 2 /*no image*/
SendMessage(hControl, LVM_SETCOLUMN, iLastClickedColumn, &lvc)
bSortAscending = TRUE
}
//ale jeśli kliknięcie było w tą samą kolumnę co poprzednio - tylko zmieniasz kierunek sortowania:
else
{
bSortAscending = (bSortAscending xor 1)
}
// dalej... ustawiasz strzałkę na kolumnie,
// zapamiętujesz nową kolumnę i sort-type i zaczynasz sortować:
lvc.iImage = bSortAscending
SendMessage(hControl, LVM_SETCOLUMN, iClickedColumn, &lvc)
SetProp(hControl, "iLastClickedCol", iClickedColumn)
SetProp(hControl, "bSortAscending", bSortAscending)
// własna struktura z danymi do sortowania:
// MYSORTDATA=column,direction,hwnd
MYSORTDATA msd
msd = {iClickedColumn, (bSortAscending<<2)-1, hControl}
// (bSortAscending<<2)-1 ustawi .direction na -1 lub 1
SendMessage(hControl, LVM_SORTITEMSEX, &msd, &fn_lv_sort)
w funkcji callback fn_lv_sort(lParam1, lParam2, msd) - 2 pierwsze parametry to indeksy itemów listview które właśnie trzeba posortować, a trzeci to pointer do naszej struktury MYSORTDATA. Pobierasz tekst z tych itemów i zwracasz wynik funkcji lstrcmpi(), ot, tyle, całe sortowanie
int fn_lv_sort(int lParam1, int lParam2, MYSORTDATA msd)
{
char txt1[MAX_PATH], txt2[MAX_PATH]
LVITEM lvi1={LVIF_TEXT, lParam1, msd.column, 0, 0, &txt1, MAX_PATH}
LVITEM lvi2={LVIF_TEXT, lParam2, msd.column, 0, 0, &txt2, MAX_PATH}
SendMessage(msd.hwnd, LVM_GETITEM, 0, &lvi1)
SendMessage(msd.hwnd, LVM_GETITEM, 0, &lvi2)
return lstrcmpi(&txt1, &txt2) * msd.direction
}
screen i full przykład+src (starałem się pisać tylko w api, łatwo przepisać do C)