【问题标题】:How to load default icons for CTreeCtrl nodes如何为 CTreeCtrl 节点加载默认图标
【发布时间】:2012-06-20 15:04:34
【问题描述】:

由于布局定制的需要,我扩展了CTreeCtrl类。

绝对需要使用CDC::DrawText()函数动态(重新)写入单个节点的文本,WITHOUT 多次调用 SetItemText() 函数(强制要求)。

然后,我编写了自己的 OnPaint() 方法实现。 我还实现了一个在 CTreeCtrl 中绘制节点的 DrawItems() 方法。

由于我不想修改除单个节点旁边的单个标签之外的任何其他内容,因此我需要重新实现大部分原始 CTreeCtrl::OnPaint() 代码。

我只有两个疑惑:

  1. 如何显示默认 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() 实现的源代码。 任何建议/帮助表示赞赏。 :-)

谢谢

它。

【问题讨论】:

    标签: mfc load icons paint treecontrol


    【解决方案1】:

    您不需要重载 onPaint。如果将树项目文本设置为 LPSTR_TEXTCALLBACK,则 CtreeCtrl 将触发消息 TVN_GETDISPINFO 以在每次显示该项目时检索新文本。如果消息处理程序位于父窗口中,则使用 ON_NOTIFY 注册消息处理程序;如果您是 CTreeCtrl 的子类,则使用 ON_NOTIFY_REFLECT 注册消息处理程序。此消息处理程序可以分配您想要的文本,但允许 treeCtrl 继续正常绘制。

    TVN_GETDISPINFO Documentation

    如果你去了父 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;
      

      }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 2015-11-11
      • 1970-01-01
      • 2013-07-11
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      相关资源
      最近更新 更多