0

レイアウトのカスタマイズが必要なため、CTreeCtrl クラスを拡張しました。

SetItemText() 関数を複数回呼び出すことなく (必須の要件) 、 CDC::DrawText()関数を使用して単一ノードのテキストを動的に(再) 書き込む必要があります。

次に、OnPaint()メソッドの独自の実装を作成しました。CTreeCtrl でノードを描画するDrawItems()メソッドも実装しました。

単一のノードの横にある単一のラベル以外は変更したくないので、元のCTreeCtrl::OnPaint()コードのほとんどを再実装する必要があります。

私は2つの疑問しか持っていません:

  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() 実装のソース コードだけです。任意の提案/ヘルプをいただければ幸いです。:-)

ありがとう

それ。

4

1 に答える 1

0

onPaint をオーバーロードする必要はありません。ツリー アイテムのテキストを LPSTR_TEXTCALLBACK として設定すると、CtreeCtrl はメッセージ TVN_GETDISPINFO を起動して、そのアイテムが表示されるたびに新しいテキストを取得します。親ウィンドウにある場合は ON_NOTIFY を使用してメッセージ ハンドラーを登録し、CTreeCtrl をサブクラス化している場合は ON_NOTIFY_REFLECT を使用してメッセージ ハンドラーを登録します。このメッセージ ハンドラーは、必要なテキストを割り当てることができますが、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;
    

    }

于 2012-10-16T23:37:32.513 に答える