如何找到标签等于字符串变量的树视图节点
How can i find treeview node by which label equals string variable?
我想感谢所有花时间查看此线程并尝试提供帮助的人。
我搜索了互联网,找不到选择标签文本与字符串变量文本相同的树视图节点的示例。
在MSDN上,我找到了消息TVM_GETISEARCHSTRING,但我不知道它是否可以用来解决我的问题。即使可以,我仍然不知道如何使用它。
我有一个字符串变量,用于保存数据库中的文本。加载程序时,树视图应选择具有相同文本的节点。
请帮助一些说明或代码片段,因为我甚至不知道如何开始编码。
我在MS Visual Studio Express 2008,Windows XP上工作,在C++,使用纯WIN32 API。
这就是全部,我再次感谢所有试图提供帮助的人。非常感谢!
编辑:
这两个答案对我来说都有好处,但我不知道如何标记它们,似乎在这个网站上只能接受一个答案。
我不能忽视他们俩为帮助我而投入的所有工作,所以我写这篇文章是为了至少通过正式声明他的解决方案对我来说也是可以接受的来回报乔纳森,只是 Tim 的解决方案更适合我的编码风格。我也会对这两个答案投赞成票。
树视图控件不提供用于搜索标签的 API。您必须手动遍历这些项目并将它们与您的字符串进行比较。
如果树视图的深度超过一个级别,则必须决定如何遍历项目(深度优先或宽度优先(。如果有多个具有相同标签的项目,这些策略可能会返回不同的项目。
实现可能如下所示:
// Helper function to return the label of a treeview item
std::wstring GetItemText( HWND hwndTV, HTREEITEM htItem )
{
static const size_t maxLen = 128;
WCHAR buffer[ maxLen + 1 ];
TVITEMW tvi = { 0 };
tvi.hItem = htItem; // Treeview item to query
tvi.mask = TVIF_TEXT; // Request text only
tvi.cchTextMax = maxLen;
tvi.pszText = &buffer[ 0 ];
if ( TreeView_GetItem( hwndTV, &tvi ) )
{
return std::wstring( tvi.pszText );
}
else
{
return std::wstring();
}
}
这是实际遍历发生的地方。以递归方式调用该函数,直到无法搜索更多项或找到匹配项。此实现使用区分大小写的比较 (wstring::operator==( const wstring& )
(。如果您需要不同的谓词,则必须根据需要修改实现。
HTREEITEM FindItemDepthFirstImpl( HWND hwndTV, HTREEITEM htStart, const std::wstring& itemText )
{
HTREEITEM htItemMatch = NULL;
HTREEITEM htItemCurrent = htStart;
// Iterate over items until there are no more items or we found a match
while ( htItemCurrent != NULL && htItemMatch == NULL )
{
if ( GetItemText( hwndTV, htItemCurrent ) == itemText )
{
htItemMatch = htItemCurrent;
}
else
{
// Traverse into child items
htItemMatch = FindItemDepthFirstImpl( hwndTV, TreeView_GetChild( hwndTV, htItemCurrent ), itemText );
}
htItemCurrent = TreeView_GetNextSibling( hwndTV, htItemCurrent );
}
return htItemMatch;
}
以下函数包装递归并将根元素作为起点传递。这是您将在代码中调用的函数。如果找到一个HTREEITEM
,它将返回一个NULL
HTREEITEM FindItem( HWND hwndTV, const std::wstring& itemText )
{
HTREEITEM htiRoot = TreeView_GetRoot( hwndTV );
return FindItemDepthFirstImpl( hwndTV, htiRoot, itemText );
}
没有记录的方法可以按项目标签搜索树视图。
TVM_GETISEARCHSTRING
消息返回用户在树中键入的搜索字符串(增量搜索模式(,但它不会触发搜索或允许您提供自己的搜索字符串。
唯一的方法是手动迭代树节点并自己比较标签。下面是一个示例函数,请注意它是递归的,并且每个子级别将使用大约半KB的堆栈。
HTREEITEM TreeView_FindLabel(HWND hWnd, HTREEITEM hItemParent, LPCWSTR pszLabel)
{
TVITEM tvi;
wchar_t wchLabel[256];
for (tvi.hItem = TreeView_GetChild(hWnd, hItemParent); tvi.hItem;
tvi.hItem = TreeView_GetNextSibling(hWnd, tvi.hItem))
{
tvi.mask = TVIF_TEXT | TVIF_CHILDREN;
tvi.pszText = wchLabel;
tvi.cchTextMax = _countof(wchLabel);
if (TreeView_GetItem(hWnd, &tvi))
{
if (_wcsicmp(tvi.pszText, pszLabel) == 0)
return tvi.hItem;
if (tvi.cChildren)
{
HTREEITEM hChildSearch = TreeView_FindLabel(hWnd, tvi.hItem, pszLabel);
if (hChildSearch) return hChildSearch;
}
}
}
return 0;
}
这不是搜索树的特别快速的方法。如果您需要进行大量搜索,最好使用std::map
自己跟踪标签和树项。例如
std::map<std::wstring, HTREEITEM> mapTreeItems;
// whenever you add an item
HTREEITEM hItem = ListView_InsertItem(...);
mapTreeItems[strLabel] = hItem;
然后,您可以使用地图按标签查找树项目。您只需记住在从树中删除项目时更新地图并擦除标注即可。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 你能重载对象变量名本身返回的内容吗
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 尝试通过多个向量访问变量时,向量下标超出范围
- 试图让变量检查数组中的某些内容
- Cpp-Tuple使用带有变量的get
- 将包含C样式数组的对象初始化为成员变量(C++)
- 当vector是tje全局变量时,c++中vector的内存管理
- 通过多个头文件使用常量变量
- 如何从未知视图中声明范围::v3::View 变量
- 如何找到标签等于字符串变量的树视图节点