![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
||||
|
||||
|
Здравствуйте.
Как организовать сортировку по клику по колонкам? Искал в инете, но толкового ни чего не неашел(быть может, искал плохо). Встречается либо код на С, либо 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; |
|
#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
|
||||
|
||||
|
Выклади свой проект.
|
|
#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
|
||||
|
||||
|
Лучше бы конечно архивом было выложить, но сойдёт и так.
Примерно так: Последний раз редактировалось 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
|
||||
|
||||
|
Сначала я поставил битмапы, затем убрал. Теперь придётся вновь добавить.
![]() Архив обновлён. Последний раз редактировалось 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.
|