为了使这篇文章尽可能简短,我只想说我需要将列表视图中的所有选定项目移动到某个(未选中)项目下面。
浏览listview文档我遇到了LVM_SORTITEMSEX
message。
如何使用上述信息来实现我的目标。
到目前为止,通过使用此消息,我能够将所有选定的项目移动到列表的底部 - > listview的排序方式是未选择的项目位于选定的项目之前。
我无法弄清楚如何在特定项目下方移动所选项目。
下面是我得到的图像,以及我想要实现的目标:
左图显示了我使用下面提交的代码时得到的结果,而右图显示了我的目标结果。
以下是相关的代码段:
// compare function -> see the documentation
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM hwnd)
{
LVITEM lvi1 = { 0 }, lvi2 = { 0 };
// get selected state of the first item
lvi1.iItem = (int)lParam1;
lvi1.iSubItem = 0;
lvi1.mask = LVIF_STATE;
lvi1.stateMask = LVIS_SELECTED;
ListView_GetItem((HWND)hwnd, &lvi1);
// get selected state of the second item
lvi2.iItem = (int)lParam2;
lvi2.iSubItem = 0;
lvi2.mask = LVIF_STATE;
lvi2.stateMask = LVIS_SELECTED;
ListView_GetItem((HWND)hwnd, &lvi2);
// if first is selected and second is not selected, swap them
if ((lvi1.state & LVIS_SELECTED) && (0 == (lvi2.state & LVIS_SELECTED)))
return 1;
return 0;
}
// somewhere in code, on button click for example
ListView_SortItemsEx(hwndListView, CompareFunc, hwndListView);
我已将listview句柄作为ListView_SortItemsEx
的第三个参数传递给我,因此我可以在ListView_GetItem
中使用CompareFunc
。
答案 0 :(得分:1)
如果我理解正确,你想通过拖放重新排列项目,并且你想要排序功能。如果要在sort proc中完成,这可能会变得复杂。另一种解决方案是首先找到安排。
LVITEM::lParam
ListView_SortItems
(不是ListView_SortItemsEx
)唯一的问题是,出于其他原因可能会使用lParam
。我们必须保存lParam
,然后在排序完成后将其恢复。
如果ListView具有LVS_SHOWSELALWAYS
,那么它也会更好。
注意,此方法会在" redMark"之前移动项目。在您的示例中,您应该设置redMark = 3
以在"项目60"
int CALLBACK CompareFunc(LPARAM lp1, LPARAM lp2, LPARAM)
{
return lp1 > lp2;
}
void sort()
{
int redMark = 3;
int count = ListView_GetItemCount(hwndListView);
std::vector<int> order;
std::vector<LPARAM> saveLParam(count);
//add everything before redMark
for (int i = 0; i < redMark; i++)
order.push_back(i);
//add highlighted items
for (int i = redMark; i < count; i++)
if (ListView_GetItemState(hwndListView, i, LVIS_SELECTED))
order.push_back(i);
//add the rest
for (int i = redMark; i < count; i++)
if (!ListView_GetItemState(hwndListView, i, LVIS_SELECTED))
order.push_back(i);
if (order.size() != count)
{
assert(0);
return;
}
//set lParam
for (int i = 0; i < count; i++)
{
LVITEM item = { 0 };
item.iItem = order[i];
item.mask = LVIF_PARAM;
//save old LParam value
ListView_GetItem(hwndListView, &item);
saveLParam[i] = item.lParam;
//set new lParam
item.lParam = i;
ListView_SetItem(hwndListView, &item);
}
ListView_SortItems(hwndListView, CompareFunc, 0);
//restore old lParam
for (int i = 0; i < count; i++)
{
LVITEM item = { 0 };
item.iItem = order[i];
item.mask = LVIF_PARAM;
item.lParam = saveLParam[order[i]];
ListView_SetItem(hwndListView, &item);
}
::SetFocus(hwndListView);
}
答案 1 :(得分:1)
<强>简介强>
LVM_SORTITEMSEX
,所有商品必须具有唯一的lParam
lParam
也不足以了解项目的原始顺序。lParam
而不是单独准备所需的物品订单,但这很脏,很容易出错。通用解决方案
lParam
LVM_SORTITEMSEX
之前,请按所需顺序准备lParam
的向量:
lParam
添加到矢量中。lParam
添加到矢量中。lParam
添加到矢量中。lParam
的订单:列表的开头,然后选择的项目保留其原始订单,然后是未选择的项目保留其原始订单。lParam
的位置,并根据此位置进行回答。例如,如果您发现第一个位置小于第二个位置,则返回一个负数。典型的方法是return (firstPos - secondPos)
,它将在一行代码中处理firstPos
和secondPos
的所有相对订单。