如何查找下一个未选择的ListView项目?
我想在ListView中搜索下一个未选中的项目,但只能使用windows API 我尝试了如何查找下一个未选择的ListView项目?,listview,delphi,delphi-2009,Listview,Delphi,Delphi 2009,我想在ListView中搜索下一个未选中的项目,但只能使用windows API 我尝试了ListView\u FindItem宏,但它不起作用。结果始终为-1: function TNewListView.NextUnselected(I: Integer): Integer; var FindInfo: TLVFindInfo; ItemInfo: TLVItem; begin if not HandleAllocated then Exit(-1) else begin
ListView\u FindItem
宏,但它不起作用。结果始终为-1:
function TNewListView.NextUnselected(I: Integer): Integer;
var FindInfo: TLVFindInfo;
ItemInfo: TLVItem;
begin
if not HandleAllocated then Exit(-1)
else begin
FillChar(ItemInfo, SizeOf(ItemInfo), 0);
ItemInfo.mask:= LVIF_STATE;
ItemInfo.state:= 0;
ItemInfo.stateMask:= LVIS_SELECTED;
FillChar(FindInfo, SizeOf(FindInfo), 0);
FindInfo.flags:= LVFI_PARAM;
FindInfo.lParam:= LPARAM(@ItemInfo);
Result:= ListView_FindItem(Handle, I, FindInfo);
end;
您正在使用以下标志调用
ListView\u FindItem()
:
LVFI_参数
搜索此结构的lParam
成员与项的LVITEM
结构的lParam
成员之间的匹配
它告诉ListView将指定的TLVFindInfo.lParam
值与每个列表项的lParam
进行比较,直到找到匹配项
如果您在非虚拟模式下使用TListView
(OwnerData=False
),列表项的lParam
值将保留其相应的TListItem
对象指针
如果在虚拟模式下使用TListView
(OwnerData=True
),列表项的lParam
值始终为0
ListView\u FindItem()
(以及底层的LVM\u FindItem
消息)可以通过其标题(完整或部分)、其lParam
1或其位置来搜索列表项,而无需其他搜索
1:例如,TListItems.IndexOf()
方法使用ListView\u FindItem()
返回指定的TListItem
对象的索引,使用lParam
搜索(仅在非虚拟模式下工作,其中每个项的lParam
是TListItem
对象指针)
您还试图执行lParam
搜索,但您使用了错误的lParam
值来搜索!您正在将TLVFindInfo.lParam
值设置为指向本地TLVItem
变量的指针,因此LVFI_参数
比较将永远找不到匹配的列表项。这就是为什么你总是得到-1的结果
ListView\u FindItem()
在您的示例中基本上执行以下逻辑:
function ListView_FindItem(hWnd: HWND; iStart: Integer; const plvfi: TLVFindInfo): Integer;
var
lvi: TLVItem;
begin
for Result := iStart+1 to ListView_GetItemCount(hWnd)-1 do
begin
FillChar(lvi, SizeOf(lvi), 0);
lvi.iIndex := Result;
lvi.mask = LVIF_PARAM;
ListView_GetItem(hWnd, lvi);
if lvi.lParam = plvfi.lParam then // <-- NEVER FINDS A MATCH!
Exit;
end;
Result := -1;
end;
function TNewListView.NextUnselected(StartIndex: Integer): Integer;
begin
if HandleAllocated then
begin
for Result := StartIndex+1 to ListView_GetItemCount(Handle)-1 do
begin
if (ListView_GetItemState(Handle, Result, LVIS_SELECTED) and LVIS_SELECTED) = 0 then
Exit;
end;
// if you want to implement wrap-around searching, uncomment this...
{
for Result := 0 to StartIndex-1 do
begin
if (ListView_GetItemState(Handle, Result, LVIS_SELECTED) and LVIS_SELECTED) = 0 then
Exit;
end;
}
end;
Result := -1;
end;
因此,您无法使用ListView\u FindItem()
/LVM\u FindItem
按状态搜索项目,它们不支持这种搜索
您可能会尝试使用ListView\u GetNextItem()
/LVM\u GetNextItem
:
搜索具有指定属性且与指定项具有指定关系的列表视图项
但是,它们只能用于搜索已启用指定特征的列表项(例如已选中LVNI_
已启用)。它们不能用于查找缺少指定特征的项目(例如选择了LVNI_
禁用)
因此,要执行所需操作,您只需手动迭代列表项,使用ListView\u GetItem()
或ListView\u GetItemState()
检索每个项的当前状态,直到找到要查找的内容
例如:
function ListView_FindItem(hWnd: HWND; iStart: Integer; const plvfi: TLVFindInfo): Integer;
var
lvi: TLVItem;
begin
for Result := iStart+1 to ListView_GetItemCount(hWnd)-1 do
begin
FillChar(lvi, SizeOf(lvi), 0);
lvi.iIndex := Result;
lvi.mask = LVIF_PARAM;
ListView_GetItem(hWnd, lvi);
if lvi.lParam = plvfi.lParam then // <-- NEVER FINDS A MATCH!
Exit;
end;
Result := -1;
end;
function TNewListView.NextUnselected(StartIndex: Integer): Integer;
begin
if HandleAllocated then
begin
for Result := StartIndex+1 to ListView_GetItemCount(Handle)-1 do
begin
if (ListView_GetItemState(Handle, Result, LVIS_SELECTED) and LVIS_SELECTED) = 0 then
Exit;
end;
// if you want to implement wrap-around searching, uncomment this...
{
for Result := 0 to StartIndex-1 do
begin
if (ListView_GetItemState(Handle, Result, LVIS_SELECTED) and LVIS_SELECTED) = 0 then
Exit;
end;
}
end;
Result := -1;
end;
或:
这两种方法都适用于您正在尝试的操作。您正在使用以下标志调用ListView\u FindItem()
:
LVFI_参数
搜索此结构的lParam
成员与项的LVITEM
结构的lParam
成员之间的匹配
它告诉ListView将指定的TLVFindInfo.lParam
值与每个列表项的lParam
进行比较,直到找到匹配项
如果您在非虚拟模式下使用TListView
(OwnerData=False
),列表项的lParam
值将保留其相应的TListItem
对象指针
如果在虚拟模式下使用TListView
(OwnerData=True
),列表项的lParam
值始终为0
ListView\u FindItem()
(以及底层的LVM\u FindItem
消息)可以通过其标题(完整或部分)、其lParam
1或其位置来搜索列表项,而无需其他搜索
1:例如,TListItems.IndexOf()
方法使用ListView\u FindItem()
返回指定的TListItem
对象的索引,使用lParam
搜索(仅在非虚拟模式下工作,其中每个项的lParam
是TListItem
对象指针)
您还试图执行lParam
搜索,但您使用了错误的lParam
值来搜索!您正在将TLVFindInfo.lParam
值设置为指向本地TLVItem
变量的指针,因此LVFI_参数
比较将永远找不到匹配的列表项。这就是为什么你总是得到-1的结果
ListView\u FindItem()
在您的示例中基本上执行以下逻辑:
function ListView_FindItem(hWnd: HWND; iStart: Integer; const plvfi: TLVFindInfo): Integer;
var
lvi: TLVItem;
begin
for Result := iStart+1 to ListView_GetItemCount(hWnd)-1 do
begin
FillChar(lvi, SizeOf(lvi), 0);
lvi.iIndex := Result;
lvi.mask = LVIF_PARAM;
ListView_GetItem(hWnd, lvi);
if lvi.lParam = plvfi.lParam then // <-- NEVER FINDS A MATCH!
Exit;
end;
Result := -1;
end;
function TNewListView.NextUnselected(StartIndex: Integer): Integer;
begin
if HandleAllocated then
begin
for Result := StartIndex+1 to ListView_GetItemCount(Handle)-1 do
begin
if (ListView_GetItemState(Handle, Result, LVIS_SELECTED) and LVIS_SELECTED) = 0 then
Exit;
end;
// if you want to implement wrap-around searching, uncomment this...
{
for Result := 0 to StartIndex-1 do
begin
if (ListView_GetItemState(Handle, Result, LVIS_SELECTED) and LVIS_SELECTED) = 0 then
Exit;
end;
}
end;
Result := -1;
end;
因此,您无法使用ListView\u FindItem()
/LVM\u FindItem
按状态搜索项目,它们不支持这种搜索
您可能会尝试使用ListView\u GetNextItem()
/LVM\u GetNextItem
:
搜索具有指定属性且与指定项具有指定关系的列表视图项
但是,它们只能用于搜索已启用指定特征的列表项(例如已选中LVNI_
已启用)。它们不能用于查找缺少指定特征的项目(例如选择了LVNI_
禁用)
因此,要执行所需操作,只需使用ListView\u GetItem()
或L手动迭代列表项即可