我正在使用自定义绘制来尝试创建透明树视图(现在我正在测试启用视觉样式时)。
我的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;
}
答案 0 :(得分:5)
不幸的是,如果不自行绘制项目,这是不可能的,抱歉。
事实证明树视图控件传统上在内部使用ExtTextOut()
函数来绘制项目标题。此函数采用显式标志参数,其中值ETO_OPAQUE
表示“当前背景颜色应用于填充矩形”。
因为此选项作为额外标志传递,而不是通过查看当前的GDI背景模式来确定,所以您无法在自定义绘制处理程序中使用SetBkMode()
来解决此问题。 DC的背景颜色属性也不支持alpha通道,因此不能只设置为透明。
由于Common Controls版本6.0和主题窗口装饰,这有点不同,但在这种情况下仍然无用:控件只调用TVP_TREEITEM
部分DrawThemeBackground()
,其余部分根据使用的主题。我在Windows 8.1的默认Aero主题中看到有这样的条目:
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
来获取文本矩形并绘制真实在其他所有内容已经由控件绘制后的文本。但是这种方法也失败了,因为即使对于空文本,也会显示出一些微小的不透明矩形。您需要先擦除该工件,然后再继续绘制文本。提出一个适用于项目状态的所有组合的代码似乎很棘手。