ListView_GetNextItem(LVNI_VISIBLEONLY)不起作用

我需要处理ListView中的所有项目(在报告模式下)对用户可见。 在debugging时,我尝试了这个:

int item; HWND hlist; for( item = ListView_GetNextItem( hlist, -1, LVNI_VISIBLEONLY ); item >= 0; item = ListView_GetNextItem( hlist, item, LVNI_VISIBLEONLY ) ) { if( ListView_IsItemVisible( hlist, item ) ) { OutputDebugString("DEBUG: Found a visible item!\n"); } } 

根据文档,GetNextItem循环应该提供所有VISIBLE项目(在Vista或更高版本中,我在Win7上)。 但是,我的debugging显示,它实际上提供了ListView中的所有项目。

于是我添加了IsItemVisible的冗余testing,当指定的项目是VISIBLE时,它被logging为返回TRUE。 不幸的是,它在for()循环中find的每一个项目都返回FALSE。

显然,我在这里错过了一些关键的(也可能是显而易见的),但是我完全丧失了它的可能性。 哦,FWIW我正在Windows 7 Professional x64下testing,而我的构build目标是WINVER 0x0601(_WIN32_WINNT也是0x0601)。

任何想法我失踪?

[更新]

我find了一个解决方法(见下文),但我仍然想知道为什么没有可见相关的function(为我)。

对于任何感兴趣的人,下面是我如何解决这个问题:

  LVITEM lvi; HWND hlist = GetDlgItem( hwnd, LST_ALARMS ); int item; RECT rcList; RECT rcItem; RECT rcHead; GetClientRect( hlist, &rcList ); // Remove the header space from the visible item area GetClientRect( ListView_GetHeader(hlist), &rcHead ); rcList.top += (rcHead.bottom - rcHead.top); memset( &lvi, 0, sizeof(lvi) ); for( item = ListView_GetNextItem( hlist, -1, LVNI_ALL ); item >= 0; item = ListView_GetNextItem( hlist, item, LVNI_ALL ) ) { if( ListView_GetItemRect( hlist, item, &rcItem, LVIR_BOUNDS ) && (rcList.top <= rcItem.top) && (rcItem.bottom <= rcList.bottom) ) { // This item is COMPLETELY visible // -- partially visible items are NOT included. lvi.mask = LVIF_PARAM; lvi.iItem = item; ListView_GetItem( hlist, &lvi ); // do stuff with item } } 

这正如我希望在这个消息开始时所做的那样工作。 我更喜欢可见性函数的易读性,但由于我需要它实际工作,我卡住比较长方形。

LVNI_VISIBLEONLY使用的可见性概念不是“现在屏幕上可见的”。 这是“没有从视图中删除”。 (如果一个对象属于一个已经被折叠的组,它将从视图中被移除。)所以如果你没有使用可折叠的分组,那么预计LVNI_VISIBLEONLY返回所有的元素。

换句话说,“可见”是指“不隐藏”,而不是“在屏幕上”。 这与IsWindowVisibleTVNI_NEXTVISIBLE和其他API使用的意义相同。

在LVM_GETNEXTITEM解释底部有一个好奇的笔记,可以解释你的问题:

备注

请注意, 仅用于Windows Vista的以下标志正在使用的任何其他标志互斥:LVNI_VISIBLEONLY,LVNI_SAMEGROUPONLY,LVNI_VISIBLEORDER,LVNI_DIRECTIONMASK和LVNI_STATEMASK。