Treeview节点有透明文本背景而不是默认白色

时间:2014-04-05 10:33:27

标签: c++ winapi treeview custom-draw

我正在使用自定义绘制来尝试创建透明树视图(现在我正在测试启用视觉样式时)。

我的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;
}

1 个答案:

答案 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_GETITEMRECTwParam=TRUE来获取文本矩形并绘制真实在其他所有内容已经由控件绘制后的文本。但是这种方法也失败了,因为即使对于空文本,也会显示出一些微小的不透明矩形。您需要先擦除该工件,然后再继续绘制文本。提出一个适用于项目状态的所有组合的代码似乎很棘手。