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 valueETO_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 theTVP_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:So, what are the alternatives?
There is always an option to return
CDRF_SKIPDEFAULT
for theCDDS_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. useTVM_GETITEMRECT
withwParam=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.