I have used the accepted solution from this question to remove checkbox from a treeview node in my WM_INITDIALOG
handler.
Upon loading, tree has a proper look. After I select the node and click on the place where checkbox would be, nothing happens ( checkbox does not appear ) which is the correct behavior.
However, if I select the node and press spacebar the checkbox is automatically added to the node.
Here is the WM_INITDIALOG
handler that illustrates the problem:
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 is interesting quote from MSDN:
Version 5.80. Displays a check box even if no image is associated with the item.
Perhaps this is the cause of my problem?
I ave tried handling TVN_KEYDOWN
and set items state or again removing the checkbox but had no success.
EDIT #2:
I have subclassed the tree, the way member Jonathan Potter suggested, and it worked:
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);
}
END OF EDIT
QUESTION:
How can I properly remove checkbox from a tree node so it never appears again ?
Thank you.
Best regards.
Sub-class the control, intercept the space key via
WM_KEYDOWN
, and don't pass the message through if the focus is on an item that you don't want to have a checkbox.