Click here to Skip to main content
15,867,453 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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:

C++
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 hNode1 = 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 hNode2 = 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.

QUESTION:

How can I properly remove checkbox from a tree node so it never appears again ?

Thank you.

Best regards.
Posted
Updated 27-Mar-14 23:41pm
v2
Comments
KarstenK 28-Mar-14 8:19am    
Why are you enabling checkboxes if you dont want them?
Rage 28-Mar-14 12:12pm    
Check the question on SO: he only wants some nodes to have a checkbox.
KarstenK 31-Mar-14 3:01am    
Checkbox-Style is for ALL items. So he needs to draw transparent pics for the not wanted.

I have subclassed the tree view and rejected spacebar if the focused item had no checkbox:
C++
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);
}
 
Share this answer
 
Two possibilities:

1. Handle TVN_KEYDOWN properly = intercept the notification and instead of wanting to change the state, simply do not call the base class when space is used.
2. You might also want to handle the TVN_ITEMCHANGED message, and reset the state in case the checkbox was checked.
 
Share this answer
 
Comments
AlwaysLearningNewStuff 28-Mar-14 13:16pm    
Thank you for answering.

Although the concept seems clear, I do not know how to handle "properly" TVN_KEYDOWN.

I have never used TVN_ITEMCHANGED message, so before writing this comment I gave it a quick look. It seems that you may be right. Also, TVN_ITEMCHANGING might also be the key.

I would ask you to edit your answer with a small code snippet or pseudo code, just so I can get the more concrete idea of what you are suggesting.

Meanwhile, I will try to handle your instructions on my own and will update my post with the resulting progress.

Thank you.

Best regards.
AlwaysLearningNewStuff 28-Mar-14 13:21pm    
After giving it a more detailed look I see that both notifications are supported from Vista onwards which is a problem since I work on Windows XP. That leaves TVN_KEYDOWN as a potential savior.

Best regards.
I you switch checkbox mode on, it is valid for ALL item, so you need to clear up yourself.
Use own graphics for "all" checkboxes. An empty pic if not needed, else own. Use DrawframeControl in a own memory bitmap

Create them on runtime and use the actual background color.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900