Ви.

Итак, я наконец понял, как работает iIntegral, член TVITEMEX. В документах MSDN не упоминается, что его установка при вставке элемента не имеет никакого эффекта, но установка после вставки элемента работает. Ура!

Однако при использовании стиля TVS_HASLINES с элементами переменной высоты линии рисуются только для верхней части элемента с iIntegral > 1. Например. если я установлю TVS_HASLINES и TVS

Вот как это выглядит (не могу публиковать изображения, WTF?)

Должен ли я вручную рисовать больше линий в ответ на NM_CUSTOMDRAW или что-то в этом роде?

0
ReturningTarzan 24 Ноя 2009 в 20:50

2 ответа

Да, Windows ничего не делает с пустым пространством, полученным при изменении высоты.

Из MSDN:

Элемент управления древовидным представлением не рисует в дополнительной области, которая появляется под содержимым элемента, но это пространство может использоваться приложением для рисования при использовании пользовательского рисования. Приложения, которые не используют пользовательскую отрисовку, должны установить это значение равным 1, так как в противном случае поведение не определено.

0
Collin Dauphinee 24 Ноя 2009 в 21:00

Хорошо, проблема решена.

Мне не удалось найти простой ответ, но я обошёл его трудным путём. В основном это просто рисование дополнительных сегментов линии в пользовательском рисовании:

// _cd is the NMTVCUSTOMDRAW structure
// ITEMHEIGHT is the fixed height set in TreeView_SetItemHeight
// linePen is HPEN of a suitable pen to draw the lines (PS_ALTERNATE etc.)
// indent is the indentation size returned from TreeView_GetIndent

case CDDS_ITEMPREPAINT : {

  // Expand line because TreeView is buggy

  RECT r = _cd->nmcd.rc;
  HDC hdc = _cd->nmcd.hdc;
  HTREEITEM hItem = (HTREEITEM) _cd->nmcd.dwItemSpec;

  if( r.bottom - r.top > ITEMHEIGHT ) {

    HGDIOBJ oldPen = SelectObject( hdc, linePen );

    // Draw any lines left of current item

    HTREEITEM hItemScan = hItem;
    for( int i = _cd->iLevel; i >= 0; --i ) {

      // Line should be drawn only if node has a next sibling to connect to

      if( TreeView_GetNextSibling( getHWnd(), hItemScan ) ) {

        // Lines seem to start 17 pixels from left edge of control. But no idea
        // where that constant comes from or if it is really constant.

        int x = 17 + indent * i;
        MoveToEx( hdc, x, r.top + ITEMHEIGHT, 0 );
        LineTo( hdc, x, r.bottom );

      }

      // Do the same for the parent

      hItemScan = TreeView_GetParent( getHWnd(), hItemScan );

    }

    SelectObject( hdc, oldPen );

  }

}

Узор кисти PS_ALTERNATE иногда не совсем совпадает с линией, нарисованной элементом управления, но это едва заметно. Что еще хуже, несмотря на то, что у меня установлены последние общие элементы управления и все пакеты обновления и исправления, в TreeView все еще есть ошибки, задокументированные еще в 2005 году. В частности, TreeView неправильно обновляет свою высоту. Единственный обходной путь, который я нашел для этого, — принудительное свертывание/расширение узлов и выполнение нескольких вызовов InvalidateRect.

Однако, если узлы переменной высоты находятся на корневом уровне, вы ничего не можете сделать. К счастью, мне это не нужно.

0
ReturningTarzan 25 Ноя 2009 в 14:07