INT GetTree (HWND hWnd, HTREEITEM hItem, HKEY *pRoot, TCHAR *pszKey,
INT nMax) {
TV_ITEM tvi;
TCHAR szName[256];
HTREEITEM hParent;
HWND hwndTV = GetDlgItem (hWnd, ID_TREEV);
memset (&tvi, 0, sizeof (tvi));
hParent = TreeView_GetParent (hwndTV, hItem);
if (hParent) {
// Get the parent of the parent of the...
GetTree (hWnd, hParent, pRoot, pszKey, nMax);
// Get the name of the item.
tvi.mask = TVIF_TEXT;
tvi.hItem = hItem;
tvi.pszText = szName;
tvi.cchTextMax = dim(szName);
TreeView_GetItem (hwndTV, &tvi); //send the TVM_GETITEM message?
lstrcat (pszKey, TEXT ("\\"));
lstrcat (pszKey, szName);
} else {
*pszKey = TEXT ('\0');
szName[0] = TEXT ('\0');
// Get the name of the item.
tvi.mask = TVIF_TEXT | TVIF_PARAM;
tvi.hItem = hItem;
tvi.pszText = szName;
tvi.cchTextMax = dim(szName);
if (TreeView_GetItem (hwndTV, &tvi))
//*pRoot = (HTREEITEM)tvi.lParam; //original
hItem = (HTREEITEM)tvi.lParam;
else {
INT rc = GetLastError();
}
}
return 0;
}
以评论“获取项目名称”开头的代码块对我来说没有意义。如果您要获取listview项,为什么代码会设置要检索的项的参数?如果您已经拥有这些值,则无需检索它们。
其次在评论“原始”附近是原始代码行,它将在嵌入式visual c ++ 4.0下使用警告进行编译,但如果将完全相同的代码复制到visual studio 2008中则无法编译。由于我没有编写任何此代码,并且我正在尝试学习,原作者是否有可能在这一行上犯了错误? * pRoot应该指向HKEY类型但他正在转换为HTREEITEM类型,由于数据类型不匹配,它应该永远不会工作?
答案 0 :(得分:3)
以注释“获取项目名称”开头的代码块对我没有意义。如果要获取listview项,为什么代码会设置要检索的项的参数,因为如果已经有值,则无需检索它们。
在那个评论之后,第一行是指定TreeView_GetItem(顺便说一下,实际上是伪装的SendMessage),我们想要检索项目的文本和相关的lParam。下一行指定了我们想要信息的项目句柄。
以下行指定必须保存检索文本的位置,即在szName缓冲区中,该缓冲区已在函数开头分配;函数调用之前的最后一行指定了这种缓冲区的大小,以避免缓冲区溢出。
我建议您查看TreeView_GetItem和TVITEM的文档,以便更好地了解正在发生的事情。
其次在注释“original”附近是原始代码行,它将使用嵌入式visual c ++下的varning进行编译,但是如果将完全相同的代码复制到visual studio 2008中则无法编译。由于我没有编写任何此代码并且我正在尝试学习原作者是否有可能在这一行上犯了错误,因为* pRoot应指向和HKEY类型但他正在转换为HTREEITEM类型,该类型应该永远不会工作数据类型不匹配?
目前还不清楚代码在那里尝试做什么;乍一看,我会说在与树视图的根节点中的每个项目相关联的lParam中存储了一个注册表项的句柄,并且该过程以这种方式检索它。不过,如果是这样的话,(HTREEITEM)演员阵容根本没有意义;可能这是一个错误,由编译器原谅,因为它将所有句柄视为普通的void *;如果我的假设是正确的,你应该保留原来的行,只需用(HKEY)替换(HTREEITEM)。
答案 1 :(得分:1)
很多时候,API调用会接收结构中的信息,并在同一结构中返回信息。如果你为TreeView_GetItem look at the documentation,它将清楚地显示它是如何运作的。
至于第二个问题,你编译为C ++吗?错误是什么?
答案 2 :(得分:1)
TreeView_GetItem
宏的LPTVITEM参数是双向使用的。
TreeView_GetItem
确实将TVM_GETITEM消息发送到树视图。这里发生的是调用者填写一点结构来说“这就是我拥有的和我想要的东西”,然后树视图将填写所请求的位。
来自TreeView_GetItem
documentation
当发送TVM_GETITEM消息时,TVITEM或TVITEMEX结构的hItem成员标识该项以检索有关的信息,并且掩码成员指定要检索的属性。
对于第二部分,我认为它看起来像是一个错误,基于变量的名称等,但您应该检查函数如何在其余代码中使用以确保。
答案 3 :(得分:1)
第一个问题非常简单:你在结构中填写少数项目来告诉你想要什么数据,然后调用TreeView_GetItem
来实际检索指定的数据。在这种情况下,您指定TVIF_TEXT
,表示您需要特定项目的文本。你还给它一个缓冲区,它将放置文本(szName
),并告诉它缓冲区有多长(因此它不会写入缓冲区的末尾)。当您致电TreeView_GetIem
时,会将该项目的文本复制到缓冲区中。
至于你的第二个问题:看起来所有代码(旧的和新的)都有些问题。一般意图似乎是检索最初传入的项目的路径,但它似乎做得相当差。它首先递归地向上走树到根。然后它检索根项目的文本,但仅进入局部变量szName
- 然后忽略(不复制到{{1} })。它会将根项目的句柄存储到szKey
(这是它最初写入hItem
的位置)。
然后,当它返回(向后“向后”回到树中)时,它会检索每个项目的文本,并将这些名称附加到pRoot
(由'\'分隔),以形成(大部分)最初传入的项的路径。不幸的是,当它这样做时,它会忽略传入的szKey
,因此它可以(显然)写入nMax
缓冲区的末尾。