Узел Treeview с прозрачным текстовым фоном вместо белого по умолчанию

Я использую пользовательское рисование, чтобы попытаться создать прозрачное древовидное представление (сейчас я тестирую, когда включены визуальные стили).

мой CDDS_PREPAINT обработчик работает нормально, дерево имеет растровое изображение фона родителя.

Я пытался добавить CDDS_ITEMPREPAINT обработчик, где я использую SetBkColor( ((LPNMCUSTOMDRAW)lParam)->hdc, TRANSPARENT ); и вернуться CDRF_NEWFONT, но это не удалось. Узел рисуется с белым фоном по умолчанию.

Как я могу сделать текстовый фон элемента прозрачным?

Спасибо.

С наилучшими пожеланиями.

Ниже приведен иллюстративный фрагмент кода:

switch( ((LPNMCUSTOMDRAW)lParam)->dwDrawStage  )
{
case CDDS_PREPAINT:
{
DrawThemeParentBackground(
((LPNMCUSTOMDRAW)lParam)->hdr.hwndFrom,
((LPNMCUSTOMDRAW)lParam)->hdc,
&((LPNMCUSTOMDRAW)lParam)->rc );

// since tree is in dialog box we need below statement
SetWindowLongPtr( hDlg, DWLP_MSGRESULT, (LONG_PTR)CDRF_NOTIFYITEMDRAW );
return TRUE;

}
break;
case CDDS_ITEMPREPAINT :  // how to properly handle this ???
{
SetBkMode( ((LPNMCUSTOMDRAW)lParam)->hdc, TRANSPARENT );

SetWindowLongPtr( hDlg, DWLP_MSGRESULT, (LONG_PTR)CDRF_NEWFONT );
return TRUE;
}
break;
}

5

Решение

К сожалению, это не легко сделать без рисования предметов, извините.

Оказывается, что Tree View Control традиционно использует ExtTextOut() внутренняя функция для рисования названий элементов. Эта функция принимает явный параметр flags, где значение ETO_OPAQUE Говорит, что «текущий цвет фона должен использоваться для заполнения прямоугольника».

Поскольку эта опция передается как дополнительный флаг и не определяется при просмотре текущего фонового режима GDI, вы не можете использовать SetBkMode() в пользовательском обработчике рисования, чтобы обойти это. Свойство background color для DC также не поддерживает альфа-канал, поэтому его нельзя просто установить прозрачным.

Так как Common Controls версии 6.0 и тематические декорации окон, это немного отличается, но все же в этом случае бесполезно: элемент управления просто вызывает DrawThemeBackground() с TVP_TREEITEM часть, а остальное обрабатывается в соответствии с используемой темой. Я вижу, например, в теме Aero по умолчанию в Windows 8.1, что есть эта запись:

ClassID  | PartID       | StateID      | Property        | Value
---------+--------------+--------------+-----------------+--------------
TreeView | TVP_TREEITEM | TREIS_NORMAL | FILLCOLOR:COLOR | 255, 255, 255

Итак, каковы альтернативы?

Всегда есть возможность вернуть CDRF_SKIPDEFAULT для CDDS_ITEMPREPAINT событие и сделать все операции отображения самостоятельно. Но тогда вам нужно позаботиться о рисовании даже линий, [+] прямоугольников, прямоугольников выделения и фокуса и всего остального.

Другой вариант — оставить текст заголовка, хранящийся в элементе управления, пустым, а затем добавить его в CDDS_ITEMPOSTPAINT — то есть использовать TVM_GETITEMRECT с wParam=TRUE чтобы получить текстовый прямоугольник и нарисовать там настоящий текст после того, как все остальное уже было нарисовано элементом управления. Но этот метод тоже не работает, потому что какой-то крошечный непрозрачный прямоугольник, очевидно, нарисован даже для пустого текста. Вам нужно будет сначала стереть этот артефакт, а затем приступить к рисованию текста самостоятельно. Придумать код, который работает для всех комбинаций состояния элемента, было сложно.

5

Другие решения

Других решений пока нет …