I_CHILDRENCALLBACK 64bit failing
I_CHILDRENCALLBACK 64bit failing
以下内容适用于32位模式,但不适用于64位模式,用于TVN_ITEMEXPANDING鼠标单击和键盘事件。
对象.h
afx_msg void OnTvnItemexpandingTreectrl(NMHDR *pNMHDR, LRESULT *pResult);
对象.cpp
BEGIN_MESSAGE_MAP(Object, CDialogEx)
ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREECTRL, OnTvnItemexpandingTreectrl)
END_MESSAGE_MAP()
void Object::LoadTree()
{
m_TreeCtrl1.DeleteAllItems();
HTREEITEM hParentItem = TVI_ROOT;
std::list<OBJ>::iterator itObj = m_Obj.begin()->m_Obj.begin();
for (size_t i = 0; i < m_Obj.begin()->m_Obj.size(); i++, ++itObj)
{
TVINSERTSTRUCT tvis;
TVITEM tvItem = { 0 };
tvItem.mask = LVIF_TEXT | LVIF_PARAM | TVIF_CHILDREN | TVIF_HANDLE | TVIF_STATE;
tvItem.cChildren = I_CHILDRENCALLBACK;
tvItem.pszText = itObj->m_TreeDesc.GetBuffer();
tvItem.cchTextMax = MAX_ITEMLEN;
tvItem.lParam = reinterpret_cast<LPARAM>(&*itObj);
tvis.item = tvItem;
tvis.hParent = TVI_ROOT;
tvis.hInsertAfter = TVI_LAST;
hParentItem = m_TreeCtrl1.InsertItem(&tvis);
RecurseBuildTree(itObj->m_Obj, m_TreeCtrl1, hParentItem, TVI_LAST);
}
hParentItem = m_TreeCtrl1.GetFirstVisibleItem();
for (size_t i = 0; i < m_Obj.begin()->m_Obj.size(); i++)
{
HTREEITEM hNext = hParentItem;
OBJ *pObjNext = reinterpret_cast<OBJ*>(m_TreeCtrl1.GetItemData(hNext));
m_TreeCtrl1.SetCheck(hNext, pObjNext->m_bItemDisplayed);
RecurseTreeSetCheck(m_TreeCtrl1, hParentItem);
hParentItem = m_TreeCtrl1.GetNextItem(hNext, TVGN_NEXT);
}
}
void Object::OnTvnItemexpandingTreectrl(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
*pResult = 0;
}
void ExpandTreeItem(CTreeCtrl &tree, HTREEITEM hItem, UINT nCode)
{
HTREEITEM hChild;
if (tree.ItemHasChildren(hItem))
{
tree.Expand(hItem, nCode);
hChild = tree.GetChildItem(hItem);
while (hChild)
{
ExpandTreeItem(tree, hChild, nCode);
hChild = tree.GetNextItem(hChild, TVGN_NEXT);
}
}
}
void Object::ToggleItemState(HTREEITEM hti, CTreeCtrl &treectrl, const HTREEITEM hParentNode)
{
if (hti == hParentNode)
{
const int iImage = treectrl.GetItemState(hParentNode, TVIS_STATEIMAGEMASK) >> 12;
OBJ *pObj = reinterpret_cast<OBJ*>(treectrl.GetItemData(hti));
pObj->m_bItemDisplayed = (iImage == 1 ? 2 : 1);
}
else
{
const int iImage = treectrl.GetItemState(hParentNode, TVIS_STATEIMAGEMASK) >> 12;
treectrl.SetItemState(hti, INDEXTOSTATEIMAGEMASK(iImage == 1 ? 2 : 1), TVIS_STATEIMAGEMASK);
OBJ *pObj = reinterpret_cast<OBJ*>(treectrl.GetItemData(hti));
pObj->m_bItemDisplayed = (iImage == 1 ? 2 : 1);
}
if (treectrl.ItemHasChildren(hti)) //failing in release mode for root level node.
{
HTREEITEM htiChild = treectrl.GetChildItem(hti);
if (htiChild)
ToggleItemState(htiChild, treectrl, hParentNode);
else
return;
HTREEITEM htiSibling = treectrl.GetNextSiblingItem(htiChild);
while (htiSibling)
{
ToggleItemState(htiSibling, treectrl, hParentNode);
htiSibling = treectrl.GetNextSiblingItem(htiSibling);
}
}
}
观察:
以下内容在 64 位发布模式下失败,但仅适用于根节点:
if (treectrl.ItemHasChildren(hti))
我有可以手动调用ExpandTreeItem()和tree的按钮。Expand() 调用 OnTvnItemexpandingTreectrl(),但在 64 位模式下,鼠标和键盘不会调用TVN_ITEMEXPANDING,对于其他事件,它可以正常工作。
我怀疑这可能与初始化有关
TVINSERTSTRUCT tvis;
TVITEM tvItem = { 0 };
但真的不知道我在找什么。
如果我需要发布更多代码,请告诉我。
谢谢
解决方案仅仅是消息的设计吗?
此处引用了文档TVM_EXPAND
当项目首次由TVM_EXPAND消息展开时,该操作将生成TVN_ITEMEXPANDING并TVN_ITEMEXPANDED通知代码,并设置项目的TVIS_EXPANDEDONCE状态标志。只要此状态标志保持设置状态,后续TVM_EXPAND消息就不会生成TVN_ITEMEXPANDING或TVN_ITEMEXPANDED通知。若要重置TVIS_EXPANDEDONCE状态标志,必须发送设置了TVE_COLLAPSE和TVE_COLLAPSERESET标志的TVM_EXPAND消息。尝试显式设置TVIS_EXPANDEDONCE将导致不可预知的行为。
我想我可能已经找到了原因:
tvItem.cChildren = I_CHILDRENCALLBACK; //<<failing in 64bit mode.
//Upto 0xFFFFFFFE works ok but not -1?
可以使用以下最少的代码来复制问题:
//header
struct ItemData
{
CString Name;
int Value;
CString ToString() const
{
CString str;
str.Format(_T("%s = %d"), Name, Value);
return str;
}
};
CTreeCtrl m_tree;
std::vector<ItemData*> m_data;
//source
void CTreeSortDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TREE, m_tree);
}
void CTreeSortDemoDlg::GenerateTreeContent()
{
ItemData* data1 = new ItemData;
data1->Value = 3;
data1->Name.Format(_T("%c%c"), 'P', data1->Value);
m_data.push_back(data1);
m_data.push_back(data1);
ItemData* data2 = new ItemData;
data2->Value = 3;
data2->Name.Format(_T("%c%c"), 'P', data2->Value);
m_data.push_back(data2);
m_data.push_back(data2);
HTREEITEM hParentItem = TVI_ROOT;
TVINSERTSTRUCT tvis;
TVITEM tvItem = { 0 };
tvItem.mask = LVIF_TEXT | LVIF_PARAM | TVIF_CHILDREN | TVIF_HANDLE | TVIF_STATE;
tvItem.cChildren = I_CHILDRENCALLBACK; //<<failing in 64bit mode. 1 works ok?
tvItem.pszText = L"Parent";
tvItem.cchTextMax = MAX_PATH;
tvItem.lParam = reinterpret_cast<LPARAM>(&m_data);
tvis.item = tvItem;
tvis.hParent = TVI_ROOT;
tvis.hInsertAfter = TVI_LAST;
hParentItem = m_tree.InsertItem(&tvis);
//////
TVINSERTSTRUCT tvis2;
TVITEM tvItem2 = { 0 };
std::vector<ItemData*>::iterator itData = m_data.begin();
tvItem2.mask = LVIF_TEXT | LVIF_PARAM | TVIF_HANDLE | TVIF_STATE;
tvItem2.cChildren = 0;
tvItem2.pszText = L"child";
tvItem2.cchTextMax = MAX_PATH;
tvItem2.lParam = reinterpret_cast<LPARAM>(&itData);
tvis2.item = tvItem2;
tvis2.hParent = hParentItem;
tvis2.hInsertAfter = TVI_LAST;
HTREEITEM hItemThis = m_tree.InsertItem(&tvis2);
}
编辑:
如果要在树生成中使用I_CHILDRENCALLBACK则还必须使用TVN_GETDISPINFO
ON_NOTIFY(TVN_GETDISPINFO, IDC_TREE, OnGetdispinfoTreectrl)
void CTreeSortDemoDlg::OnGetdispinfoTreectrl(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
TVITEM* pItem = &(pTVDispInfo)->item;
ItemData *pData = reinterpret_cast<ItemData*>(pItem->lParam);
if (pItem->mask & TVIF_CHILDREN)
{
if (pData != NULL)
{
pItem->cChildren = I_CHILDRENCALLBACK;
}
}
}
奇怪的是行为如何表现自己。
相关文章:
- c++ visual studio 64bit | save registers value
- CreateDepthStencilView() is failing
- CGAL static_cast failing
- Qt C++ Modulo Operator Failing
- Qt on Visual Studio 2010 and win7 64bit
- Google协议缓冲区-64bit VS2010
- I_CHILDRENCALLBACK 64bit failing
- C++ GetBinaryType Failing
- IDWriteFactory::CreateTextFormat() failing
- 为VS2010、WINDOWS7、64BIT生成CUDA示例时出错MSB3721
- 未解析的包含:<stdio.h> in Eclipse helios(Windows 7 64bit)
- fopen() failing
- C++ Minmax Failing
- C# and Ghostscript 64bit
- IE9 GetPropertyByName failing
- Using Clang on Mingw 64bit
- Windows 64bit shared dll Tesseract?
- C++: gethostname() failing
- 64bit atomicAdd in CUDA
- Qt QMap.insert() failing