|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
||||
|
||||
Сортировка в ListView WinApi
Здравствуйте.
Как организовать сортировку по клику по колонкам? Искал в инете, но толкового ни чего не неашел(быть может, искал плохо). Встречается либо код на С, либо VCL(Аналогичное у меня есть). Никак не соображу. Подскажите пожалуйста. |
#2
|
||||
|
||||
LVM_SORTITEMS
Пишу программы за еду. __________________ |
#3
|
||||
|
||||
Я так понимаю SendMessage(LV, LVM_SORTITEMS, 0, 0) ?
|
#4
|
||||
|
||||
LVM_SORTITEMS
Цитата:
Пишу программы за еду. __________________ |
#5
|
||||
|
||||
Попытался переделать
Код:
if(nmhdr->code == LVN_COLUMNCLICK) { NM_LISTVIEW *pnm; pnm = (NM_LISTVIEW *) lParam; // заполняем структуру NM_LISTVIEW // сортируем ListView_SortItems(pnm->hdr.hwndFrom, // идентификатор окна List View CompareListViewProc, // указатель на функцию сравнения (LPARAM) (pnm->iSubItem)); // если в функцию сравнения нужно передать какое либо значение, этот параметр для этого. я тут передаю просто номер столбца break; int CALLBACK CompareListViewProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { CHAR Buff1[1024]={0}; CHAR Buff2[1024]={0}; LPSTR lpStr1, lpStr2; INT iNum1=0, iNum2=0; INT iResult, iIndex=0; LVFINDINFO ItemInfo; ItemInfo.flags=LVFI_PARAM; // копируешь в буфера сравниваемые строки ItemInfo.lParam=lParam1; iIndex=ListView_FindItem(hWndListView, -1, &ItemInfo); ListView_GetItemText(hWndListView, iIndex, (int)lParamSort, Buff1, sizeof(Buff1)); lpStr1=Buff1; ItemInfo.lParam=lParam2; iIndex=ListView_FindItem(hWndListView, -1, &ItemInfo); ListView_GetItemText(hWndListView, iIndex, (int)lParamSort, Buff2, sizeof(Buff2)); lpStr2=Buff2; if(lpStr1 && lpStr2) { switch(lParamSort) { // тут по номеру столбца, делается сравнение case 0: case 4: iResult=strcmpi(lpStr1, lpStr2); break; case 1: case 2: case 3: iNum1 = atoi(lpStr2); iNum2 = atoi(lpStr1); iResult = iNum2 - iNum1; break; default: iResult=0; break; } } // возврат результата сравнения return(iResult); } Вот что получилось(в моем Listview 7 колонок): Код:
LVN_COLUMNCLICK : ListView_SortItems(LV, @CompareFunc, PNMLISTVIEW(lParam).iSubItem); function CompareFunc(LPARAM1, LPARAM2, lParamSort: Cardinal): Integer; stdcall; var Buff1, Buff2 : array[0..1024] of Char; lpStr1, lpStr2 : string; iNum1, iNum2, iResult, iIndex : Integer; ItemInfo : LV_FINDINFO; begin ItemInfo.flags := LVFI_PARAM; // копируешь в буфера сравниваемые строки ItemInfo.lParam := lParam1; iIndex := ListView_FindItem(LV, -1, &ItemInfo); ListView_GetItemText(LV, iIndex, lParamSort, Buff1, sizeof(Buff1)); lpStr1 := Buff1; ItemInfo.lParam := lParam2; iIndex := ListView_FindItem(lParamSort, -1, &ItemInfo); ListView_GetItemText(lParamSort, iIndex, lParamSort, Buff2, sizeof(Buff2)); lpStr2 := Buff2; // if(lpStr1 and lpStr2) then case (lParamSort) of // тут по номеру столбца, делается сравнение // 0: 0..7: iResult := lstrcmp(PChar(lpStr1), PChar(lpStr2)); // break; // case 1: // case 2: { 3: iNum1 = atoi(lpStr2); iNum2 = atoi(lpStr1); iResult = iNum2 - iNum1; break; default: } // break; // возврат результата сравнения end; // iResult:=0; Result := (iResult); end; Поправте пожалуйста, а то чертовщина какято тварится(вроде строки бегают, но не так как надо). |
#6
|
||||
|
||||
Взято из действующей программы
Код:
function CompareFunc(lParam1, lParam2, SortType : Longint) : Integer; stdcall; var lvi : LV_ITEM; Size1, Size2 : Integer; Column : Word; St1, St2 : String; begin Column := LOWORD(SortType); lvi.mask := LVIF_TEXT; if Column = 0 then begin Result := AnsiCompareText(LV_GetItemText(hLV, lParam1, 0), LV_GetItemText(hLV, lParam2, 0)); end else if Column = LVSize + 1 then begin try Size1 := StrToInt(Copy(LV_GetItemText(hLV, lParam1, Column), 1, Pos(' ', LV_GetItemText(hLV, lParam1, Column)) - 1)); Size2 := StrToInt(Copy(LV_GetItemText(hLV, lParam2, Column), 1, Pos(' ', LV_GetItemText(hLV, lParam2, Column)) - 1)); Result := Size1 - Size2; except Result := 0; end; end else begin St1 := LV_GetItemText(hLV, lParam1, Column); St2 := LV_GetItemText(hLV, lParam2, Column); Result := AnsiCompareText(St1, St2); if (St1 = '') or (St2 = '') then Result := 0; end; if isSorted then Result := Result else Result := -Result; end; procedure DrawColumnImage(hHeader : HWND; Column : Integer; bmp : Integer); var Item : THDITEM; begin FillChar(Item, SizeOf(ThdItem), 0); Item.Mask := HDI_FORMAT; if (not Header_GetItem(hHeader, Column, Item)) then Exit; if (Bmp = 0) then begin Item.mask := HDI_FORMAT; Item.fmt := Item.fmt and not (HDF_BITMAP or HDF_BITMAP_ON_RIGHT); end else begin Item.mask := Item.Mask or HDI_BITMAP; Item.fmt := Item.fmt or HDF_BITMAP or HDF_BITMAP_ON_RIGHT; Item.hbm := Bmp; end; Header_SetItem(hHeader, Column, Item); end; procedure SortItems(hList : HWND; Column, bmArUp, bmArDn : Integer); var hHeader : HWND; Item : THDITEM; I : Integer; St : String; bm : Integer; begin hLV := hList; St := ''; for I := 0 to LV_Count(hList) - 1 do St := St + LV_GetItemText(hList, I, Column); if (St = '') then begin hHeader := ListView_GetHeader(hList); if (hHeader = 0) then Exit; DrawColumnImage(hHeader, 0, 0); Exit; end; hHeader := ListView_GetHeader(hList); if (hHeader = 0) then Exit; if Column = SortColumn then isSorted := not isSorted else begin SortColumn := Column; isSorted := True; end; if (Column <> -1) then begin FillChar(Item, SizeOf(THDITEM), 0); Item.mask := Item.mask or HDI_LPARAM; if (not Header_GetItem(hHeader, Column, Item)) then Exit; Item.lParam := not Item.lParam; Header_SetItem(hHeader, Column, Item); end; for I := 0 to LV_Count(hList) - 1 do begin if I <> Column then bm := 0 else begin if isSorted then bm := bmArUp else bm := bmArDn; end; DrawColumnImage(hHeader, I, bm); end; if (Column <> -1) then ListView_SortItems(hList, @CompareFunc, MAKELONG(Column, ord(isSorted))); end; Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#7
|
||||
|
||||
Здравствуйте.
А в Код:
LVN_COLUMNCLICK : ListView_SortItems(LV, @CompareFunc, PNMLISTVIEW(lParam).iSubItem); Код:
LVSize: Integer; isSorted: Boolean; Где они еще используются? isSorted - прямая, обратная сортировка. LVSize = я так понимаю, клик по SubItem. Забыл: У меня только строки. Кликаю по колонке №0- - нет сотировки. Кликаю по любой другой -- сортирует по №0. что не так? заполняю: Код:
var item : tLVITEM; ... for zz := 0 to 10 do begin FillChar(item, sizeof(item), 0 ); item.mask := LVIF_TEXT; item.iItem := ListView_GetItemCount(lv); item.pszText := PChar(inttostr(zz)); ListView_InsertItem(LV, Item); for b := 1 to 7 do begin item.iSubItem := b; item.pszText := PChar(nttostr(random(100))); ListView_SetItem(LV, item); end; end; Код:
LVN_COLUMNCLICK: begin if (LVSize = PNMLISTVIEW(lParam).iSubItem) then // Если это та же самая колонка - меняем направление сортировки isSorted := not isSorted else // иначе - прямая сортировка isSorted := False; LVSize := PNMLISTVIEW(lParam).iSubItem; ListView_SortItems(LV, @CompareFunc, PNMLISTVIEW(lParam).iSubItem); end; Код:
function CompareFunc(lParam1, lParam2, SortType : Longint) : Integer; stdcall; var lvi : LV_ITEM; Size1, Size2 : Integer; Column : Word; St1, St2 : String; begin Column := LOWORD(SortType); lvi.mask := LVIF_TEXT; if Column = 0 then begin Result := AnsiCompareText(LV_GetItemText(LV, lParam1, 0), LV_GetItemText(LV, lParam2, 0)); end else if Column = LVSize + 1 then {begin try Size1 := StrToInt(Copy(LV_GetItemText(LV, lParam1, Column), 1, Pos(' ', LV_GetItemText(LV, lParam1, Column)) - 1)); Size2 := StrToInt(Copy(LV_GetItemText(LV, lParam2, Column), 1, Pos(' ', LV_GetItemText(LV, lParam2, Column)) - 1)); Result := Size1 - Size2; except Result := 0; end; end else } begin St1 := LV_GetItemText(LV, lParam1, Column); St2 := LV_GetItemText(LV, lParam2, Column); Result := AnsiCompareText(St1, St2); if (St1 = '') or (St2 = '') then Result := 0; end; // SetWindowText(Form, IntToStr(LVSize)); } if isSorted then Result := Result else Result := -Result; end; Последний раз редактировалось Stalker2-42, 24.11.2014 в 20:33. |
#8
|
||||
|
||||
Выклади свой проект.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#9
|
||||
|
||||
Оставил тока ListView.
Код:
program Project1; uses Windows, Messages, CommCtrl, SysUtils; var WndClassEx : TWndClassEx; Form, LV : hwnd; MMsg: Msg; item : tLVITEM; LVSize: Integer; isSorted: Boolean; Const LVID = 13; function LV_GetItemText(hList : HWND; Index, SubItem : Integer) : String; var Buf : array [0..MAX_PATH] of Char; begin ZeroMemory(@Buf, SizeOf(Buf)); ListView_GetItemText(hList, Index, SubItem, Buf, SizeOf(Buf)); if Buf[0] <> #0 then Result := Buf; end; function CompareFunc(lParam1, lParam2, SortType : Longint) : Integer; stdcall; var lvi : LV_ITEM; Size1, Size2 : Integer; Column : Word; St1, St2 : String; begin Column := LOWORD(SortType); lvi.mask := LVIF_TEXT; if Column = 0 then begin Result := AnsiCompareText(LV_GetItemText(LV, lParam1, 0), LV_GetItemText(LV, lParam2, 0)); end else if Column = LVSize + 1 then {begin try Size1 := StrToInt(Copy(LV_GetItemText(LV, lParam1, Column), 1, Pos(' ', LV_GetItemText(LV, lParam1, Column)) - 1)); Size2 := StrToInt(Copy(LV_GetItemText(LV, lParam2, Column), 1, Pos(' ', LV_GetItemText(LV, lParam2, Column)) - 1)); Result := Size1 - Size2; except Result := 0; end; end else } begin St1 := LV_GetItemText(LV, lParam1, Column); St2 := LV_GetItemText(LV, lParam2, Column); Result := AnsiCompareText(St1, St2); if (St1 = '') or (St2 = '') then Result := 0; end; // SetWindowText(Form, IntToStr(LVSize)); } if isSorted then Result := Result else Result := -Result; end; Function WinProc(Forma: hwnd; Msg: UINT; wparam: WParam; LParam: LPARAM): lresult; Stdcall; Var lvc : TLVColumn; I, zz, B : Integer; rect : TRect; Begin Result := 0; Case Msg Of WM_GETMINMAXINFO: begin PMinMaxInfo(LParam)^.ptMinTrackSize := Point(300, 300); end; WM_CREATE: begin GetClientRect(Forma, Rect); LV :=CreateWindowEx(WS_EX_CLIENTEDGE,'SysListView32', '1', WS_CHILD or WS_VISIBLE or LVS_REPORT or LVS_SHOWSELALWAYS or LVS_SINGLESEL , 0, 35, Rect.Right ,Rect.Bottom - 105,Forma, LVID, HInstance, nil); SendMessage(lv, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT or LVS_EX_GRIDLINES or LVS_EX_INFOTIP); lvc.fmt := LVCFMT_CENTER; lvc.mask := LVCF_TEXT or LVCF_WIDTH; lvc.pszText := '0'; lvc.cx := 250; lvc.iSubItem := 0; ListView_InsertColumn(lv, 0, lvc); lvc.mask := lvc.mask or LVCF_FMT or LVCF_SUBITEM; lvc.pszText := '1'; lvc.cx := 60; lvc.iSubItem := 1; ListView_InsertColumn(LV, 1, lvc); lvc.mask := lvc.mask or LVCF_FMT or LVCF_SUBITEM; lvc.pszText := '2'; lvc.cx := 50; lvc.iSubItem := 2; ListView_InsertColumn(LV, 2, lvc); lvc.mask := lvc.mask or LVCF_FMT or LVCF_SUBITEM; lvc.pszText := '3'; lvc.cx := 100; lvc.iSubItem := 3; ListView_InsertColumn(LV, 3, lvc); lvc.mask := lvc.mask or LVCF_FMT or LVCF_SUBITEM; lvc.pszText := '4'; lvc.cx := 100; lvc.iSubItem := 4; ListView_InsertColumn(LV, 4, lvc); lvc.mask := lvc.mask or LVCF_FMT or LVCF_SUBITEM; lvc.pszText := '5'; lvc.cx := 100; lvc.iSubItem := 5; ListView_InsertColumn(LV, 5, lvc); lvc.mask := lvc.mask or LVCF_FMT or LVCF_SUBITEM; lvc.pszText := '6'; lvc.cx := 100; lvc.iSubItem := 6; ListView_InsertColumn(LV, 6, lvc); lvc.mask := lvc.mask or LVCF_FMT or LVCF_SUBITEM; lvc.fmt := LVCFMT_LEFT; lvc.pszText := '7'; lvc.cx := LVSCW_AUTOSIZE_USEHEADER;//250; lvc.iSubItem := 7; ListView_InsertColumn(LV, 7, lvc); end; WM_SIZE: Begin GetClientRect(Form, Rect); SetWindowPos(LV, 0, 0, 35, Rect.Right, Rect.Bottom - 82, SWP_NOZORDER); SendMessage(LV, LVM_SETCOLUMNWIDTH, 7, LVSCW_AUTOSIZE_USEHEADER); End; WM_NOTIFY: begin if PNMHDR(lParam).hwndFrom = LV then case {PNMHDR}PNMLISTVIEW(lParam)^.hdr.code of LVN_COLUMNCLICK: begin if (LVSize = PNMLISTVIEW(lParam).iSubItem) then isSorted := not isSorted else isSorted := False; LVSize := PNMLISTVIEW(lParam).iSubItem; ListView_SortItems(LV, @CompareFunc, PNMLISTVIEW(lParam).iSubItem); end; end; end; WM_SHOWWINDOW: begin for zz := 0 to 10 do begin FillChar(item, sizeof(item), 0 ); item.mask := LVIF_TEXT; item.iItem := ListView_GetItemCount(lv); item.pszText := PChar(inttostr(zz)); ListView_InsertItem(LV, Item); for b := 1 to 7 do begin item.iSubItem := b; item.pszText := PChar(inttostr(random(100))); ListView_SetItem(LV, item); end; end; end; WM_DESTROY: begin PostQuitMessage(0); end; Else Result := DefWindowProc(Forma, Msg, WParam, LParam); End; End; Procedure WinMain; Begin FillChar(WndClassEx, SizeOf(TWndClassEx), 0); WndClassEx.cbSize := SizeOf(TWndClassEx); WndClassEx.lpszClassName := 'APIWindow'; WndClassEx.style := CS_HREDRAW Or CS_VREDRAW; WndClassEx.hInstance := HInstance; WndClassEx.lpfnWndProc := @WinProc; WndClassEx.cbClsExtra := 0; WndClassEx.cbWndExtra := 0; WndClassEx.hIcon := LoadIcon(HInstance, MakeIntResource('MAINICON')); WndClassEx.hIconSm := LoadIcon(HInstance, MakeIntResource('MAINICON')); WndClassEx.hCursor := LoadCursor(0, IDC_ARROW); WndClassEx.hbrBackground := COLOR_BTNFACE + 1; WndClassEx.lpszMenuName := NIL; If RegisterClassEx(WndClassEx) = 0 Then MessageBox(0, 'Невозможно зарегистрировать класс окна1', 'Ошибка', MB_OK Or MB_ICONHAND) Else Begin Form := CreateWindowEx(0, WndClassEx.lpszClassName, '123', WS_OVERLAPPEDWINDOW, 500,100, 420, 400, 0, 0, HInstance, NIL); If Form = 0 Then MessageBox (0, 'Окно1 не создалось!', 'Ошибка', MB_OK Or MB_ICONHAND) Else Begin ShowWindow (Form, SW_SHOWNORMAL); While GetMessage(MMsg, 0, 0, 0) Do Begin TranslateMessage(MMsg); DispatchMessage(MMsg); End; Halt(MMsg.WParam); End; End; End; begin WinMain; end. Последний раз редактировалось Stalker2-42, 25.11.2014 в 01:14. |
#10
|
||||
|
||||
Лучше бы конечно архивом было выложить, но сойдёт и так.
Примерно так: Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. Последний раз редактировалось angvelem, 01.12.2014 в 04:53. |
Этот пользователь сказал Спасибо angvelem за это полезное сообщение: | ||
Stalker2-42 (25.11.2014)
|
#11
|
||||
|
||||
Спасибо. SortItems проигнорировал. А про UpdateParam вообще не додумался бы.
Я ваш должник. Еще вопрос, все про ту же сортировку(ОНА РАБОТАЕТ), В частности про направление сортировки столбцов: Код:
procedure SortItems(hList : HWND; Column : Integer); var hHeader : HWND; Item : THDITEM; I : Integer; St : String; begin ..... for I := 0 to LV_Count(hList) - 1 do begin if I <> Column then bm := 0 else begin if isSorted then bm := bmArUp else bm := bmArDn; end; DrawColumnImage(hHeader, I, bm); end; end; bmArUp и bmArDn ?????? Уж простите дурака . Хотелось бы до конца доделать, а то сортировка по какому столбцу и в каком направление, непонятно. Последний раз редактировалось Stalker2-42, 25.11.2014 в 17:59. |
#12
|
||||
|
||||
Сначала я поставил битмапы, затем убрал. Теперь придётся вновь добавить.
Архив обновлён. Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. Последний раз редактировалось angvelem, 26.11.2014 в 01:14. |
Этот пользователь сказал Спасибо angvelem за это полезное сообщение: | ||
Stalker2-42 (26.11.2014)
|
#13
|
||||
|
||||
Здравствуйте. Все прекрасно работает. Спасибо.
|
#14
|
||||
|
||||
Код:
procedure SortItems(hList : HWND; Column, bmArUp, bmArDn : Integer); var hHeader : HWND; Item, ItemA : THDITEM; I : Integer; St : String; bm : Integer; begin // hLV := hList; St := ''; for I := 0 to ListView_GetItemCount(hList) - 1 do St := St + LV_GetItemText(hList, I, Column); if St = '' then begin hHeader := ListView_GetHeader(hList); if hHeader = 0 then Exit; DrawColumnImage(hHeader, 0, 0); Exit; end; hHeader := ListView_GetHeader(hList); if hHeader = 0 then Exit; if Column = SortColumn then isSorted := not isSorted else begin SortColumn := Column; isSorted := True; end; if Column <> -1 then begin FillChar(Item, SizeOf(THDITEM), 0); Item.mask := Item.mask or HDI_LPARAM; if (not Header_GetItem(hHeader, Column, Item)) then Exit; Item.lParam := not Item.lParam; Header_SetItem(hHeader, Column, Item); end; FillChar(ItemA, SizeOf(ThdItem), 0); ItemA.Mask := HDI_FORMAT; if (not Header_GetItem(hHeader, Column, ItemA)) then Exit; // ItemA.mask := HDI_FORMAT; ItemA.fmt := ItemA.fmt and not (HDF_BITMAP or HDF_SORTUP or HDF_SORTDOWN); for I := 0 to ListView_GetItemCount(hList) - 1 do begin if I <> Column then bm := 0 else begin if isSorted then // bm := bmArUp begin ItemA.mask := ItemA.Mask or HDI_BITMAP; ItemA.fmt := ItemA.fmt or HDF_SORTUP ;//Header_SetItem(hHeader, Column, Item); // ItemA.hbm := bmp; end else // bm := bmArDn; begin ItemA.mask := ItemA.Mask or HDI_BITMAP; ItemA.fmt := ItemA.fmt or HDF_SORTDOWN ; // Item.hbm := bmp; end; end; Header_SetItem(hHeader, Column, ItemA); //DrawColumnImage(hHeader, I, bm);SetWindowText(form, IntToStr(bm)); end; if Column <> -1 then ListView_SortItems(hList, @CompareFunc, MAKELONG(Column, ord(isSorted))); end; как можно исравить? И сделать как в проводнике(стрелочки)? |
#15
|
||||
|
||||
Свой код я ещё писал под Win98, поэтому нужно полистать MSDN.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |