Как загрузить иконки по умолчанию для узлов CTreeCtrl

Из-за необходимости настройки макета я расширил класс CTreeCtrl.

Мне абсолютно необходимо использовать функцию CDC::DrawText() для динамического (пере) написания текста отдельных узлов, БЕЗ вызова функции SetItemText() более одного раза (обязательный реквизит).

Затем я написал свою собственную реализацию метода OnPaint(). Я также реализовал метод DrawItems(), который рисует узлы в CTreeCtrl.

Поскольку я не хочу изменять ничего, кроме отдельных меток рядом с отдельными узлами, мне нужно заново реализовать большую часть оригинального кода CTreeCtrl::OnPaint().

У меня только два сомнения:

  1. Как я могу показать значки DEFAULT CTreeCtrl? Я не нуждаюсь / не хочу пользовательских значков.
  2. Как восстановить макет режима выбора по умолчанию для отдельных узлов?

Просто выбранные узлы должны быть выделены.

Некоторые части упрощенного, авто-пояснительного кода ниже:

void MyDlg::OnPaint()
{
    CPaintDC dc(this);
    CDC dc_ff;  
    CBitmap bm_ff;
    CBitmap *bm_old;
    CFont *font;
    CFont *old_font;
    CFont fontDC;
    int old_mode;
    GetClientRect(&m_Rect);

    dc_ff.CreateCompatibleDC( &dc );
    bm_ff.CreateCompatibleBitmap( &dc, m_Rect.Width(), m_Rect.Height() ); 
    dc_ff.SelectObject( &bm_ff ); 
    font = GetFont();
    old_font = dc_ff.SelectObject( font );

    // Could / Should be called here?
    CWnd::DefWindowProc(WM_PAINT, (WPARAM)dc.m_hDC, 0);

    old_mode = dc_ff.SetBkMode(TRANSPARENT);

    dc_ff.FillSolidRect(m_Rect, dc_ff.GetBkColor());

    DrawItems( &dc_ff ); // DrawItems() member function draws single nodes of CTreeCtrl

    dc.BitBlt( m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height(), &dc_ff, 0, 0, SRCCOPY);

    dc_ff.SelectObject( old_font );
    dc_ff.SetBkMode( old_mode );
    dc_ff.SelectObject( bm_old ); 
}

void MyDlg::DrawItems( CDC *pDC )
{
    // draw items
    HTREEITEM show_item, parent;
    CRect rc_item;
    CString name;
    DWORD tree_style;
    int count = 0;
    int state;
    bool selected;
    bool has_children;

    show_item = GetFirstVisibleItem();
    if ( show_item == NULL )
        return;
    color = pDC->GetTextColor();
    tree_style = ::GetWindowLong( m_hWnd, GWL_STYLE ); 

    do
    {
        state = GetItemState( show_item, TVIF_STATE );
        parent = GetParentItem( show_item );
        has_children = ItemHasChildren( show_item ) || parent == NULL;
        selected = (state & TVIS_SELECTED) && ((this == GetFocus()) || 
                (tree_style & TVS_SHOWSELALWAYS));

        if ( GetItemRect( show_item, rc_item, TRUE ) )
        {
            if ( has_children  || selected )
            {
                if ( selected )
                {
                    // HERE i need to 
                }
                else

                // do some stuff...

                if ( has_children )
                {
                    HICON icon;
                    // HERE I need to load CTreeCtrl nodes _DEFAULT_icon
                    icon = LoadIcon(NULL, IDI_ASTERISK);
                    if ( icon != NULL )
                        DrawIconEx( pDC->m_hDC, rc_item.left - 18, rc_item.top, icon, 16, 16,0,0, DI_NORMAL ); 
                }
            }
            if ( !has_children )
            {
                HICON icon;
                *// HERE I need to load CTreeCtrl nodes _DEFAULT_icon*
                icon = LoadIcon(NULL, IDI_ASTERISK);
                if ( icon != NULL )
                    DrawIconEx( pDC->m_hDC, rc_item.left - 18, rc_item.top, icon, 16, 16,0,0, DI_NORMAL ); 
            }
            name = GetItemText( show_item );
            // ...
            if ( selected )
            {
                pDC->DrawText( "Temp", rc_item, DT_LEFT );
            }
            else
            {
                pDC->DrawText( "Temp", rc_item, DT_LEFT );
            }
            //if ( state & TVIS_BOLD )
            //  pDC->SelectObject( font );
        }
    } while ( (show_item = GetNextVisibleItem( show_item )) != NULL );
}

Все, что мне нужно, это исходный код почти стандартной реализации CTreeCtrl::OnPaint(). Любое предложение / помощь приветствуется.:-)

Спасибо

ЭТО.

1 ответ

Решение

Вам не нужно перегружать OnPaint. Если вы установите текст элементов дерева как LPSTR_TEXTCALLBACK, CtreeCtrl будет запускать сообщение TVN_GETDISPINFO для получения нового текста каждый раз, когда отображается этот элемент. Повторно зарегистрируйте обработчик сообщений, используя ON_NOTIFY, если он находится в родительском окне, или ON_NOTIFY_REFLECT, если вы создаете подкласс CTreeCtrl. Этот обработчик сообщений может назначать нужный вам текст, но позволяет treeCtrl продолжать рисовать как обычно.

TVN_GETDISPINFO Документация

Если вы пошли по родительскому маршруту Cwnd, вам нужно

  1. Поэтому вам нужно назначить обработчик сообщений в файле cpp:

    BEGIN_MESSAGE_MAP (MyCWnd, CWnd)

    ON_NOTIFY (TVN_GETDISPINFO, tree_ctl_id, CustomTreeControl:: OnGetdispinfo) END_MESSAGE_MAP ()

  2. Прототип функции в заголовке

    afx_msg void OnGetdispinfo( NMHDR* pNMHDR, LRESULT* pResult);

  3. Это в конце вашего определения класса

    DECLARE_MESSAGE_MAP()

  4. И фактическая функция для обработки запроса

    void ColumnTreeControl:: OnGetdispinfo (NMHDR * pNMHDR, LRESULT * pResult) {NMTVDISPINFO * pDispInfo = (NMTVDISPINFO ) pNMHDR; TVITEM item = & pDispInfo-> item;

    if(item->mask & TVIF_TEXT )
    {
             item->pszText " YOUR CODE HERE";
    }
    *pResult = 0;
    

    }

Другие вопросы по тегам