I am using custom draw to try and create transparent tree view ( for now I am testing when Visual Styles are enabled ).
My CDDS_PREPAINT
handler works fine, tree has parent's background bitmap drawn properly.
I tried to add CDDS_ITEMPREPAINT
handler where I use SetBkColor( ((LPNMCUSTOMDRAW)lParam)->hdc, TRANSPARENT );
and return CDRF_NEWFONT
, but that failed. Node is drawn with default white background.
How can I make item's text background transparent?
Thank you.
Best regards.
Below is the illustrative code snippet:
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;
}
Unfortunately, this is not easily possible without drawing the items yourself, sorry.
It turns out the Tree View Control has traditionally used ExtTextOut()
function internally to draw the item titles. This function takes an explicit flags parameter, where value ETO_OPAQUE
says that "the current background color should be used to fill the rectangle".
Because this option is passed as an extra flag and not determined by looking at the current GDI background mode, you can't use SetBkMode()
in a custom draw handler to work around this. The background color property of a DC does not support alpha channel either, so it cannot be just set transparent.
Since Common Controls version 6.0 and themed window decorations, this is a bit different, but still not useful in this case: the control just calls DrawThemeBackground()
with the TVP_TREEITEM
part and the rest is handled according to the theme being used. I see e.g in the default Aero theme in Windows 8.1 that there is this entry:
ClassID | PartID | StateID | Property | Value
---------+--------------+--------------+-----------------+--------------
TreeView | TVP_TREEITEM | TREIS_NORMAL | FILLCOLOR:COLOR | 255, 255, 255
So, what are the alternatives?
There is always an option to return CDRF_SKIPDEFAULT
for the CDDS_ITEMPREPAINT
event and do all the display operations yourself. But then you need to take care of drawing even the lines, [+] boxes, selection and focus rectangles and everything else.
Another option might be to leave the title text stored in the control empty, then add it in CDDS_ITEMPOSTPAINT
- i.e. use TVM_GETITEMRECT
with wParam=TRUE
to get the text rectangle and draw the real text there after everything else has been already painted by the control. But this method fails too, because some tiny opaque rectangle is apparently drawn even for empty text. You'd need to erase that artifact first, only then proceed with drawing the text youself. Coming up with a code which does work for all combinations of item state seemed tricky.