近日同事遇到一个问题找我一起研究,在某个对话框内使用了一个CTreeCtrl,其中实现了一个重置Tree的函数ResetTree(),这个函数的主要作用是把数据往Tree里面塞,塞完了再把数的每个子节点闭合。这个函数在打开对话框的时候调用一次,也在获得新物品的时候调用。
其中的诡异之处就是,在打开对话框后(调用了一次ResetTree()),点击相应是正常的。在不对TreeCtrl点击展开的时候,获得物品时调用ResetTree也是正常的。但若在有展开项的时候调用,则会发现点击异常,看似总是点击在第一项。
ResetTree中的操作很一般 先调用CTreeCtrl::DeleteAllItems()把数据清空,然后一个一个把数据往里面塞。
调查发现,在出问题的时候,GetSelectedItem()返回的值并非预期的值。而正确的时候,GetSelectedItem() 则表现得十分正常。
于是去拦截CTreeCtrl传给父窗口的WM_NOTIFY消息,TVN_SELCHANGED,发现在出现问题的情况下,会收到这个变化。再进一步得知,是在DeleteAllItems()的时候,导致了这个变动。
于是怀疑是CTreeCtrl::DeleteAllItems()的,网上google下,果然是。
http://www.codeproject.com/Messages/881742/Problem-with-CTreeCtrl-DeleteAllItems.aspx
据说是个bug,也有不少说这个时候DeleteAllItems()会有各种问题。最后采用的解决方法是在DeleteAllItems()前后调用SetRedraw
m_cTree.SetRedraw(FALSE); m_cTree.DeleteAllItems(); m_cTree.SetRedraw(TRUE);
1.Tree Control Item Selection
http://msdn.microsoft.com/en-us/library/a9a9f1t7%28v=vs.80%29.aspx