【问题标题】:Removed checkbox reappears in treeview node when spacebar is pressed按下空格键时,删除的复选框重新出现在树视图节点中
【发布时间】:2014-04-01 06:17:30
【问题描述】:

我已使用公认的解决方案 from this question 从我的 WM_INITDIALOG 处理程序中的 treeview 节点 中删除 checkbox

加载后,tree 具有正确的外观。在我选择节点并单击 checkbox 所在的位置后,什么也没有发生(checkbox 没有出现),这是正确的行为。

但是,如果我选择节点并按 空格键 复选框 会自动添加到节点。

这是说明问题的WM_INITDIALOG 处理程序:

case WM_INITDIALOG:
    {
        // get treeview handle

        HWND TreeView = GetDlgItem( hDlg, IDC_TREE1 );

        /************ enable checkboxes **************/

        DWORD dwStyle = GetWindowLong( TreeView , GWL_STYLE);
        dwStyle |= TVS_CHECKBOXES;
        SetWindowLongPtr( TreeView , GWL_STYLE, dwStyle );

        /************ add items and subitems **********/

        // add root item

        TVINSERTSTRUCT tvis = {0};

        tvis.item.mask = TVIF_TEXT;
        tvis.item.pszText = L"This is root item";
        tvis.hInsertAfter = TVI_LAST;
        tvis.hParent = TVI_ROOT;

        HTREEITEM hRootItem = reinterpret_cast<HTREEITEM>( SendMessage( TreeView ,
            TVM_INSERTITEM, 0, reinterpret_cast<LPARAM>( &tvis ) ) );

        // and here is an example of removing a checkbox 

        TVITEM tvi;
        tvi.hItem = hRootItem ;
        tvi.mask = TVIF_STATE;
        tvi.stateMask = TVIS_STATEIMAGEMASK;
        tvi.state = 0;
        TreeView_SetItem( TreeView, &tvi );

        // add firts subitem for the hTreeItem

        memset( &tvis, 0, sizeof(TVINSERTSTRUCT) );

        tvis.item.mask = TVIF_TEXT;
        tvis.item.pszText = L"This is first subitem";
        tvis.hInsertAfter = TVI_LAST;
        tvis.hParent = hRootItem;

        HTREEITEM hTreeSubItem1 = reinterpret_cast<HTREEITEM>( SendMessage( TreeView ,
            TVM_INSERTITEM, 0, reinterpret_cast<LPARAM>( &tvis ) ) );

        // now we insert second subitem for hRootItem

        memset( &tvis, 0, sizeof(TVINSERTSTRUCT) );

        tvis.item.mask = TVIF_TEXT | TVIF_STATE; // added extra flag
        tvis.item.pszText = L"This is second subitem";
        tvis.hInsertAfter = TVI_LAST;
        tvis.hParent = hRootItem;

        HTREEITEM hTreeSubItem2 = reinterpret_cast<HTREEITEM>( SendMessage( TreeView , 
            TVM_INSERTITEM, 0, reinterpret_cast<LPARAM>( &tvis ) ) );
    }
    return (INT_PTR)TRUE;  

Here 是来自 MSDN 的有趣引用:

5.80 版。 即使没有图像与该项目相关联,也会显示一个复选框。

也许这是我的问题的原因?

我尝试过处理TVN_KEYDOWN 并设置项目状态或再次删除复选框,但没有成功。

编辑#2:

我按照成员 Jonathan Potter 建议的方式对树进行了子类化,并且它起作用了:

LRESULT CALLBACK TreeProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, 
    UINT_PTR uIdSubclass, DWORD_PTR dwRefData )
{
    switch (message)
    {
    case WM_KEYDOWN:
        {
            // reject spacebar if tree node doesn't have checkbox
            if( wParam == VK_SPACE ) 
            {
                HTREEITEM ht = TreeView_GetSelection( hwnd );

                TVITEM tvItem;

                // Prepare to receive the desired information.
                tvItem.mask = TVIF_HANDLE | TVIF_STATE;
                tvItem.hItem = (HTREEITEM)ht;
                tvItem.stateMask = TVIS_STATEIMAGEMASK;

                // Request the information.
                TreeView_GetItem( hwnd, &tvItem );

                // reject if it's not checked, or pass default value otherwise
                switch( tvItem.state >> 12 )
                {
                    case 0:
                        MessageBeep(0);
                        return FALSE;
                        break;
                    case 1:
                    case 2:
                    default:
                        return ::DefSubclassProc( hwnd, message, wParam, lParam );
                        break;
                }               
            }
        }
        break;
    case WM_NCDESTROY:
        ::RemoveWindowSubclass( hwnd, TreeProc, 0 );
        break;
    }
    return ::DefSubclassProc( hwnd, message, wParam, lParam);
}

编辑结束

问题:

我怎样才能正确地从 树节点 中删除 checkbox 使其不再出现

谢谢。

最好的问候。

【问题讨论】:

  • 对控件进行子类化,拦截空格键,如果焦点在你不想有复选框的项目上,不要通过。
  • @JonathanPotter:我曾尝试实施您的建议,但失败了。我用子类化代码编辑了我的帖子。用于测试节点是否没有复选框/已选中/未选中的代码有效。我还检索了焦点节点的文本,以确保我用TreeView_GetSelection() 测试了正确的节点并且文本是正确的。似乎树首先检查/取消检查节点然后我得到WM_CHAR。您能否查看我提交的短代码 sn-p 以便我们验证我的结论或纠正我的错误(如果有)?谢谢你。最好的问候。
  • 尝试捕获 WM_KEYDOWN 而不是 WM_CHAR
  • 成功了!谢谢!如果您将此作为答案发布,我将投票并正式接受(我必须继承并拦截WM_KEYDOWN)。最好的问候。

标签: c++ winapi checkbox treeview keyboard-shortcuts


【解决方案1】:

对控件进行子类化,通过WM_KEYDOWN 截取空格键,如果焦点位于您不希望有复选框的项目上,则不要传递消息。

【讨论】:

  • 我终于获得了赏金。再次感谢你的帮助。最好的问候,直到下一次。
  • 一如既往的乐于助人!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-10
  • 1970-01-01
  • 2011-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多