使用节点和复选框创建TreeView [英] Creating TreeView with nodes and checkboxes

查看:40
本文介绍了使用节点和复选框创建TreeView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经创建了这样的TreeView:

I have created TreeView like this:

TreeView=CreateWindowEx(0, WC_TREEVIEW, TEXT("Tree View"), WS_VISIBLE | WS_CHILD, 0, 0, 200, 500, hwnd, (HMENU)ID_TREE_VIEW, GetModuleHandle(NULL), NULL);

现在,我向其中添加了一个项目,如此网站.

Now I added one item to it like shown on this website.

没关系,但是经过数小时的谷歌搜索,我仍然没有找到以下问题的答案:

It all okay, but after hours and hours of googling I still didn't found answer to these questions:

  1. 如何添加子项(节点)?

  1. How to add subitems (nodes)?

如何在每个项目上添加复选框(如何确定是否选中了指定的复选框)?

How to add checkbox on each item (how to determine if specified checkbox is checked)?

推荐答案

EDIT#4:

为响应OP请求,我添加了一个示例,该示例从父节点中删除了复选框.

EDIT #4:

In response to OPs request, I have added an example that removes checkbox from a parent node.

当用户选择一个节点并按空格键时,复选框仍然出现.

这个问题解决了这个问题.

我添加了创建已经检查过的节点的代码.

I have added the code that creates a node that is already checked.

这是 WM_CREATE 处理程序中的第二个子项.

It is the second child bode in the WM_CREATE handler.

case WM_CREATE:
    {
        // this is your treeview

        TreeView = CreateWindowEx(0, WC_TREEVIEW, 
            TEXT("Tree View"), WS_VISIBLE | WS_CHILD, 
            0, 0, 200, 500, 
            hwnd, (HMENU)ID_TREE_VIEW, GetModuleHandle(NULL), NULL);

        /************ 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 
        // from a specific item/subitem in case you ever need it

        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;

        // for demonstration purposes let us check this node;
        // to do that add the following code, and add the extra flag for 
        // mask member like above
        tvis.item.stateMask = TVIS_STATEIMAGEMASK;
        tvis.item.state = 2 << 12;

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

        // let us expand the root node so we can see if checked state is really set
        TreeView_Expand( TreeView, hRootItem, TVE_EXPAND );
    }
    return 0L;

编辑#2:

这里是解释如何检查项目是否已选中的部分(现在,当您单击复选框和按空格键时,它会正确检查!! ):

case WM_NOTIFY:
    {
        LPNMHDR lpnmh = (LPNMHDR) lParam;

        if( lpnmh->idFrom == ID_TREE_VIEW  )  // if this is our treeview control
        {
            switch( lpnmh->code )  // let us filter notifications
            {
            case TVN_KEYDOWN:  // tree has keyboard focus and user pressed a key
                {

                    LPNMTVKEYDOWN ptvkd = (LPNMTVKEYDOWN)lParam; 

                    if( ptvkd->wVKey == VK_SPACE )  // if user pressed spacebar
                    {

                        // get the currently selected item
                        HTREEITEM ht = TreeView_GetSelection( ptvkd->hdr.hwndFrom );

                        // Prepare to test items state

                        TVITEM tvItem;

                        tvItem.mask = TVIF_HANDLE | TVIF_STATE;
                        tvItem.hItem = (HTREEITEM)ht;
                        tvItem.stateMask = TVIS_STATEIMAGEMASK;

                        // Request the information.
                        TreeView_GetItem( ptvkd->hdr.hwndFrom, &tvItem );

                        // Return zero if it's not checked, or nonzero otherwise.
                        if( (BOOL)(tvItem.state >> 12) - 1 )
                            MessageBox( hwnd, L"Not checked!", L"", MB_OK );
                        else
                            MessageBox( hwnd, L"Checked!", L"", MB_OK );

                    }
                }
                return 0L;  // see the documentation for TVN_KEYDOWN

            case NM_CLICK:  // user clicked on a tree
                {
                    TVHITTESTINFO ht = {0};

                    DWORD dwpos = GetMessagePos();

                    // include <windowsx.h> and <windows.h> header files
                    ht.pt.x = GET_X_LPARAM(dwpos);
                    ht.pt.y = GET_Y_LPARAM(dwpos);
                    MapWindowPoints( HWND_DESKTOP, lpnmh->hwndFrom, &ht.pt, 1 );

                    TreeView_HitTest(lpnmh->hwndFrom, &ht);

                    if(TVHT_ONITEMSTATEICON & ht.flags)
                    {
                        // Prepare to receive the desired information.

                        TVITEM tvItem;

                        tvItem.mask = TVIF_HANDLE | TVIF_STATE;
                        tvItem.hItem = (HTREEITEM)ht.hItem;
                        tvItem.stateMask = TVIS_STATEIMAGEMASK;

                        // Request the information.
                        TreeView_GetItem( lpnmh->hwndFrom, &tvItem );

                        // Return zero if it's not checked, or nonzero otherwise.
                        if( (BOOL)(tvItem.state >> 12) - 1 )
                            MessageBox( hwnd, L"Not checked!", L"", MB_OK );
                        else
                            MessageBox( hwnd, L"Checked!", L"", MB_OK );

                    }
                }
            default:
                break;
        }
    }
}
break;

按下空格键时进行正确测试的相关想法是处理 TVN_KEYDOWN 消息.

The relevant idea for proper testing when spacebar is pressed is handling of TVN_KEYDOWN message.

我们使用此消息来获取

We use this message to get NMTVKEYDOWN structure filled, which will give us virtual key code of the pressed button and the HWND of the treeview that sent the notification.

现在,我们使用 TreeView_GetItem()宏来获取当前选定的节点,并以与进行测试时相同的方式检查其状态.

Now we use TreeView_GetItem() macro to get the currently selected node and we check its state the same way we did when we did hit testing.

我唯一的问题是有关 TVN_KEYDOWN 的文档中的这一部分:

My only problem is concerning this part from the documentation for TVN_KEYDOWN:

返回值

如果lParam的wVKey成员是字符键码,则该字符将用作增量搜索的一部分.返回非零从增量搜索中排除字符,或零以包括字符搜索中的字符.对于所有其他键,返回值为忽略了.

If the wVKey member of lParam is a character key code, the character will be used as part of an incremental search. Return nonzero to exclude the character from the incremental search, or zero to include the character in the search. For all other keys, the return value is ignored.

我只是不知道如何处理返回结果,所以我放了 0L .

I just do not know what to do with the return result so I have put 0L.

重要说明::如果您需要从对话框过程中返回值,请使用以下内容:

Important note: If you need to return value from dialog box procedure use something like this:

SetWindowLongPtr( hwnd, DWLP_MSGRESULT, (LONG_PTR)1 );
return TRUE;

请参见本文档中的返回值 ,并使用 SetWindowLong ,因此您可以同时支持 x32 Windows的x64 版本.

仅此而已.希望您解决了问题.如果您需要进一步的帮助,请发表评论.

That would be all. Hopefully you have your problem solved. If you need further help leave a comment.

我从未检查过是否检查了树项目,但我相信

I have never done checking if tree item is checked but I believe that accepted answer to this question is the way to go.

注意:

如果有人可以提供代码段来显示如何确定 treeview 节点是否被选中,我将不胜感激.

I would highly appreciate if there someone who can provide code snippet for showing how to determine if treeview node is checked or not.

这篇关于使用节点和复选框创建TreeView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆