Как загрузить иконки по умолчанию для узлов CTreeCtrl
Из-за необходимости настройки макета я расширил класс CTreeCtrl.
Мне абсолютно необходимо использовать функцию CDC::DrawText() для динамического (пере) написания текста отдельных узлов, БЕЗ вызова функции SetItemText() более одного раза (обязательный реквизит).
Затем я написал свою собственную реализацию метода OnPaint(). Я также реализовал метод DrawItems(), который рисует узлы в CTreeCtrl.
Поскольку я не хочу изменять ничего, кроме отдельных меток рядом с отдельными узлами, мне нужно заново реализовать большую часть оригинального кода CTreeCtrl::OnPaint().
У меня только два сомнения:
- Как я могу показать значки DEFAULT CTreeCtrl? Я не нуждаюсь / не хочу пользовательских значков.
- Как восстановить макет режима выбора по умолчанию для отдельных узлов?
Просто выбранные узлы должны быть выделены.
Некоторые части упрощенного, авто-пояснительного кода ниже:
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 продолжать рисовать как обычно.
Если вы пошли по родительскому маршруту Cwnd, вам нужно
Поэтому вам нужно назначить обработчик сообщений в файле cpp:
BEGIN_MESSAGE_MAP (MyCWnd, CWnd)
ON_NOTIFY (TVN_GETDISPINFO, tree_ctl_id, CustomTreeControl:: OnGetdispinfo) END_MESSAGE_MAP ()
Прототип функции в заголовке
afx_msg void OnGetdispinfo( NMHDR* pNMHDR, LRESULT* pResult);
Это в конце вашего определения класса
DECLARE_MESSAGE_MAP()
И фактическая функция для обработки запроса
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;
}