65.9K
CodeProject is changing. Read more.
Home

Tree ComboBox Control

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (17 votes)

Apr 27, 2011

CPOL

1 min read

viewsIcon

78085

downloadIcon

4829

Tree ComboBox Control

TreeCComboBoxControl/treecombobox.gif

Introduction

Recently, I needed a tree control inside a combobox, and during my search on Google I found something, but it was a little more complicated than I required. I started to draft one myself, and am sharing the result with you.

Using the Code

Everything is based on CTreeComboBox, which is derived from the standard CComboBox. Here I have a CComboTreeCtrl variable member and methods characteristic to a tree control. In CTreeComboBox::PreSubclassWindow, I create and initialize m_Tree and stretch on the combobox dropdown list.

void CTreeComboBox::PreSubclassWindow() 
{
    // TODO: Add your specialized code here and/or call the base class

    CComboBox::PreSubclassWindow();

    CRect rect(0, 0, 0, 0);
    DWORD dwStyle =  WS_POPUP | WS_BORDER | TVS_DISABLEDRAGDROP | 
    TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_FULLROWSELECT | 
    TVS_CHECKBOXES;
    m_Tree.CreateEx(0, WC_TREEVIEW, NULL, dwStyle, rect, GetParent(), 0, NULL);
    m_Tree.Init(this);

    GetClientRect(rect);
    SetDroppedWidth(rect.Width());
    SetDroppedHeight(m_droppedHeight);

    dwStyle = 0x03 & GetStyle();
    ASSERT(dwStyle == CBS_DROPDOWNLIST);
}

At first click, or arrow key down, the tree window will open.

void CTreeComboBox::OnLButtonDown(UINT nFlags, CPoint point) 
{
    // TODO: Add your message handler code here and/or call default

    m_bTree = ! m_bTree;
    if(m_bTree)DisplayTree();

//    CComboBox::OnLButtonDown(nFlags, point);
}

and:

BOOL CTreeComboBox::PreTranslateMessage(MSG* pMsg) 
{
    // TODO: Add your specialized code here and/or call the base class

    if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_DOWN)
    {
        DisplayTree();
        return TRUE;
    }

    return CComboBox::PreTranslateMessage(pMsg);
}

But the tree window should close at second click, escape key, Enter key, or lost focus. I tried a few ways but I failed, so my solution was to send to the parent (CTreeComboBox) a message to close.

LRESULT CTreeComboBox::OnCloseControl(WPARAM wParam, LPARAM lParam)
{
    TreeCtrlDone();
    m_Tree.ShowWindow(SW_HIDE);
    m_bTree = FALSE;

    return 1;
}

ComboBox must setup with CBS_DROPDOWNLIST or else you'll be ASSERTed :)

In order to use this control, you need #include "TreeComboBox.h" and further handle combobox like it is a tree control (you can see how in the sample project).

Enjoy it!

History

  • 26 April, 2011: Initial version.
  • 20 February, 2012: Added CTreeCtrl and GetTreeCtrl() methods to the CTreeComboBox class, so now it has full access to the tree control.
  • 10 May, 2013: Updated the control archive.
  • 16 Oct., 2014: The drop down is dropped by screen position (down or up); The drop down can not be closed by Alt+F4.
  • 14 Nov. 2014: I updated the code in order to be used on newer versions of Visual Studio (VS2008 for instance).
  • 18 Nov. 2014: I added posibility that combobox could be dropped down through F4. I added CComboTreeCtrlExt class in order to be customized tree control of combobox without mess up CComboTreeCtrl class.