gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 15:19:37 29 4
gpt4 key购买 nike

我是这样创建 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);

现在我向其中添加了一项,如 this website 所示.

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

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

  2. 如何在每个项目上添加复选框(如何判断指定的复选框是否被选中)?

最佳答案

编辑#4:

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

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

This question解决了这个问题。

编辑#3:

我添加了创建已检查节点的代码。

它是 WM_CREATE 处理程序中的第二个子节点。

编辑结束

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信息。

我们使用此消息获取 NMTVKEYDOWN structure填充,这将为我们提供按下按钮的虚拟键码和发送通知的 TreeView 的 HWND

现在我们使用 TreeView_GetItem() 宏来获取当前选定的节点,并像我们进行 HitTest 时一样检查其状态。

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

Return value

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

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

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

Return value in this documentation的备注并使用 SetWindowLongPtr而不是 SetWindowLong所以您可以同时支持 x32x64 版本的 Windows

就这样吧。希望您的问题得到解决。如果您需要进一步的帮助,请发表评论。

编辑结束

我从来没有检查过是否检查了树项,但我相信 accepted answer to this question是要走的路。

注意:

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

关于c++ - 使用节点和复选框创建 TreeView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22441747/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com