C++ 使用节点和复选框创建TreeView

C++ 使用节点和复选框创建TreeView,c++,winapi,C++,Winapi,我创建了如下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); SetWindowLongPtr( hwnd, DWLP_MSGRESULT, (LONG_PTR)1 ); return TRUE; 现在我添加了一项,

我创建了如下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);
SetWindowLongPtr( hwnd, DWLP_MSGRESULT, (LONG_PTR)1 );
return TRUE;
现在我添加了一项,如图所示

这一切都没问题,但经过数小时的谷歌搜索,我仍然没有找到这些问题的答案:

如何添加子项节点

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

编辑4: 为了响应OPs请求,我添加了一个从父节点删除复选框的示例

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

解决了这个问题

编辑3: 我添加了创建已检查节点的代码

它是WM_CREATE处理程序中的第二个子bode

编辑结束 请参阅和的备注,以便您可以同时支持x32和x64版本的Windows

就这些了。希望你的问题解决了。如果您需要进一步的帮助,请留下评论

编辑结束 我从来没有做过检查,如果树项目是检查,但我相信这是一条路要走

注:

如果有人能提供代码片段来演示如何确定是否检查了treeview节点,我将不胜感激

编辑4: 为了响应OPs请求,我添加了一个从父节点删除复选框的示例

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

解决了这个问题

编辑3: 我添加了创建已检查节点的代码

它是WM_CREATE处理程序中的第二个子bode

编辑结束 请参阅和的备注,以便您可以同时支持x32和x64版本的Windows

就这些了。希望你的问题解决了。如果您需要进一步的帮助,请留下评论

编辑结束 我从来没有做过检查,如果树项目是检查,但我相信这是一条路要走

注:


如果有人能提供代码片段来演示如何确定是否检查了treeview节点,我将不胜感激

试试这个宝箱,我重新编辑了我的答案。这一次,单击树的复选框和按空格键都成功覆盖。唯一需要解决的难题在编辑的底部有详细的描述,我相信这是一个小问题。祝你们好运,并致以最良好的祝愿。若要在删除复选框后提供一致的行为,必须对树视图进行子类化,以避免用户按下空格键时出现错误。您可以找到详细的解释和代码。如果您必须支持XP+,则需要使用此方法,否则您可能会更好地使用此消息。请尝试此宝箱,我已再次编辑了我的答案。这一次,单击树的复选框和按空格键都成功覆盖。唯一需要解决的难题在编辑的底部有详细的描述,我相信这是一个小问题。祝你们好运,并致以最良好的祝愿。若要在删除复选框后提供一致的行为,必须对树视图进行子类化,以避免用户按下空格键时出现错误。您可以找到详细的解释和代码。如果您必须支持XP+,则需要使用此方法,否则您最好使用此消息。+1。但是你的代码有错误。您在使用空格键后失去了选择。非常感谢您提供的精彩详细的答案。我已经将代码添加到我的程序中,它可以正常工作。现在唯一困扰我的是如何在程序启动时设置一些复选框。在向树视图插入项之前,我尝试过向状态变量添加位,如下所示:tvis.item.state=1@user3213103:该链接使用。我用一种更简单的方法在WM_CREATE处理程序中编辑了我的答案。测试后,我可以确认它的工作。如果需要显示节点,可以使用消息或宏以编程方式展开父节点。谢谢你的接受。致以最良好的祝愿。@user2120666:要在按空格键并关闭消息框后将选择还原到节点,只需在if/else块后添加以下两行代码:SetFocus ptvkd->hdr.hwndFrom;TreeView_选择ptvkd->hdr.hwndFrom、tvItem.hItem、TVGN_插入符号;现在一切都按你喜欢的方式进行。希望这对你有帮助。向您致以最良好的问候,再次感谢您的投票+1.但是你的代码有错误。您在使用空格键后失去了选择。非常感谢您提供的精彩详细的答案。我已经将代码添加到我的程序中,它可以正常工作。现在唯一困扰我的是如何在程序启动时设置一些复选框。在向树视图插入项之前,我尝试过向状态变量添加位,如下所示:tvis.item.state=1@user3213103:该链接使用。我用一种更简单的方法在WM_CREATE处理程序中编辑了我的答案。测试后,我可以确认它的工作。如果需要显示节点,可以使用消息或宏以编程方式展开父节点。谢谢你的接受。致以最诚挚的问候。@user2120666:为了将所选内容还原为“否” de按空格键关闭消息框后,只需在if/else块后添加以下2行代码:SetFocus ptvkd->hdr.hwndFrom;TreeView_选择ptvkd->hdr.hwndFrom、tvItem.hItem、TVGN_插入符号;现在一切都按你喜欢的方式进行。希望这对你有帮助。向您致以最良好的问候,再次感谢您的投票!
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;
SetWindowLongPtr( hwnd, DWLP_MSGRESULT, (LONG_PTR)1 );
return TRUE;