最近工作中遇到个问题,MFC中CTreeCtrl类的函数GetItemData。具体为返回值在类型转换后内部变量无法访问(内存无法读取)。

查找MSDN关与此函数的解释为

CTreeCtrl::GetItemData

Visual Studio 2012 调用该函数检索该32位特定的值与该指定的项目。

DWORD_PTR GetItemData(HTREEITEM hItem) const;

参数:

hItem-数据将检索项的句柄。

返回值:

32位特定的值与 hItem指定的项。

以下是示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
HTREEITEM hmyItem = m_TreeCtrl.GetSelectedItem();

// Delete all of the children of hmyItem whose item data is
// not equal to zero.
if (m_TreeCtrl.ItemHasChildren(hmyItem))
{
HTREEITEM hNextItem;
HTREEITEM hChildItem = m_TreeCtrl.GetChildItem(hmyItem);

while (hChildItem != NULL)
{
hNextItem = m_TreeCtrl.GetNextItem(hChildItem, TVGN_NEXT);

if (m_TreeCtrl.GetItemData(hChildItem) != 0)
{
m_TreeCtrl.DeleteItem(hChildItem);
}

hChildItem = hNextItem;
}
}

又查找对应的CTreeCtrl::SetItemDataMSDN解释如下:

CTreeCtrl::SetItemData>

Visual Studio 2012 调用此函数将32位特定的值与该指定的项目。

BOOL SetItemData(
HTREEITEM hItem,
DWORD_PTR dwData
);

参数:

hItem-数据将检索项的句柄。
dwData-32位特定的值与 hItem指定的项。

返回值:

如果成功,非零;否则为0。

示例代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CString   str;
HTREEITEM hItem;

// Insert 20 items into the tree control making every item's
// data be the handle of the item.
for (int i = 0; i < 20; i++)
{
str.Format(TEXT("item %d"), i);
hItem = m_TreeCtrl.InsertItem(str);

if (hItem != NULL)
{
m_TreeCtrl.SetItemData(hItem, (DWORD_PTR)hItem);
}
}

问题所在

  • 此函数返回值固定为32位或特定类型,Debug时应注意节点设置时的类型一致(DWORDDWORD_PTR)。

  • 若设置Data(CTreeCtrl::SetItemData)类型不正确会造成内存不能对齐,获取的结果内存无法访问。

  • 调试时注意此问题,SetItemDataGetItemData应注意类型正确统一。

以后使用或者调试的时候需要额外注意,避免这个小问题在调试时耽误时间。

另外,17年春节刚过,祝自己和朋友们新年一切顺利。😆