为啥我的 CTreeCtrl 复选框不检查?

Posted

技术标签:

【中文标题】为啥我的 CTreeCtrl 复选框不检查?【英文标题】:Why aren't my CTreeCtrl checkboxes checking?为什么我的 CTreeCtrl 复选框不检查? 【发布时间】:2009-08-17 18:13:33 【问题描述】:

我有一个 MFC CTreeCtrl 卡在一个打开 TVS_CHECKBOXES 样式的对话框中。我的所有树项目旁边都有复选框。在 OnInitDialog 中,我使用 CTreeCtrl::SetCheck 设置了某些项目的选中状态,但是当显示树时,树中的所有项目都没有被选中。 SetCheck 正在返回 TRUE。用鼠标检查项目工作正常。有人遇到过这种情况吗?

【问题讨论】:

【参考方案1】:

找出问题所在。我在视觉工作室资源编辑器中设置了 TVS_CHECKBOXES 样式。显然,这导致了我在初始检查时遇到的问题。相反,您必须这样做

m_nodeTree.ModifyStyle (TVS_CHECKBOXES, 0); m_nodeTree.ModifyStyle (0, TVS_CHECKBOXES);

在 OnInitDialog 中填充树之前。一旦我这样做了,一切都很好。

【讨论】:

这似乎是一个愚蠢的答案,但它也完美解决了我的问题 :) 作为记录,在这里使用 VS2008... 不错 - 我自己也遇到了这个错误。对我来说,只有在我不指定图像列表时才会出现问题。 这在the documentation中被调用:“如果你想使用这种风格,你必须在创建树视图控件之后和填充树之前使用SetWindowLong设置TVS_CHECKBOXES风格。否则,根据时间问题,复选框可能未选中。” (您工作太辛苦了,关闭并重新打开样式。只需在代码中打开一次即可。不要在资源编辑器中打开它。)【参考方案2】:

我使用以下代码创建了 myTreeCtrl:

myTreeCtrl.Create(WS_CHILD|TVS_HASBUTTONS|TVS_CHECKBOX|, CtrlRect, this, IDC_TREECTRL);

我尝试检查OnInitialDialog() 中的一些项目并遇到了同样的问题。 我试过了:

myTreeCtrl.ModifyStyle(TVS_CHECKBOXES, 0);
myTreeCtrl.ModifyStyle(0, TVS_CHECKBOXES);

现在它可以正常工作了。

不仅如此,它不会检查项目是否不在窗口的可见部分中。我必须在OnVScroll() 上触发。

【讨论】:

【参考方案3】:

树形视图控件中的复选框很古怪。作为documented:

如果您想使用这种样式,您必须在创建树视图控件之后和填充树之前使用SetWindowLong 设置 TVS_CHECKBOXES 样式。否则,复选框可能会显示为未选中,具体取决于时间问题。

换句话说,您不能在控件创建时设置TVS_CHECKBOXES 树视图样式。在 Visual Studio 的资源编辑器(它只是 .rc 脚本的图形前端)中设置的控件样式在控件创建时使用。

解决方案相当简单:创建不带TVS_CHECKBOXES 样式的控件,并在代码中将其打开,然后再填充控件:

::SetWindowLong( hwndTreeView, GWL_STYLE,
                 ::GetWindowLong( hwndTreeView, GWL_STYLE ) | TVS_CHECKBOXES );

在 MFC 中可以使用

m_treeView.ModifyStyle( 0x0, TVS_CHECKBOXES );

其中m_treeView 是树视图控件实例变量。


背景资料:

复选框不是初始树视图控件实现的一部分。它们是后来添加的,遵循方案开发人员在可用之前使用所需的复选框:通过使用状态图像列表并在树视图项上设置状态项索引。

需要解决的问题之一是确定复选框的大小。如果树视图控件分配了图像列表(“普通图像列表”),则复选框应与这些图像的大小相匹配。否则,复选框应使用系统小图标大小。这样做的一个推论是,如果您使用的是“普通图像列表”,则需要在设置图像列表之后启用TVS_CHECKBOXES 样式

另一个怪癖是,状态图像索引0 表示“没有状态图像”(1 指的是“未检查”状态项图像)。如果将项添加到具有TVS_CHECKBOXES 样式集的树视图控件,则该控件会将状态项索引设置为1(即使您指定了0)。这就是为什么在创建时设置 TVS_CHECKBOXES 样式时所有项目都未选中的原因。这也意味着,如果您想要一个没有状态图像的树视图项,则必须添加树视图项,然后手动重置状态项索引。

这应该是足够的信息,可以理解和解决所提出的问题。树视图的实现还有很多,但我会把它留给更适合写它的人。请参阅下面的参考资料


参考资料:

Raymond Chen (The Old New Thing) 发表了一篇涵盖树视图控件怪癖的系列文章。并非所有条目都与这个问题直接相关,但每一个条目都具有洞察力和价值,无论以何种方式,所以我将全部列出:

The TVS_CHECKBOXES style is quirky, which is a polite way of saying that it is crazy Beware of the leaked image list when using the TVS_CHECKBOXES style Creating tree view check boxes manually: A simple state image list Creating tree view check boxes manually: Responding to clicks Creating tree view check boxes manually: Themed check boxes Tree view check boxes: A sordid history Tree view check boxes: The extended check box states

【讨论】:

以上是关于为啥我的 CTreeCtrl 复选框不检查?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MFC 中处理 CTreeCtrl 的状态更改事件

为啥比较选中的属性不适用于检查至少一个复选框被选中?

为啥我的 Handsontable 自定义编辑器中的复选框不切换?

为啥 jQuery 看不到已自动选中的复选框?

为啥我的复选框不能影响我的 div 内容?

为啥滚动网格中的 jqxgrid 未选中复选框或单选按钮列?