【问题标题】:Treeview node with transparent text background instead of default white具有透明文本背景而不是默认白色的 Treeview 节点
【发布时间】:2014-05-02 21:59:53
【问题描述】:

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

我的CDDS_PREPAINT 处理程序工作正常,树的父级背景位图绘制正确。

我尝试在使用SetBkColor( ((LPNMCUSTOMDRAW)lParam)->hdc, TRANSPARENT ); 的地方添加CDDS_ITEMPREPAINT 处理程序并返回CDRF_NEWFONT,但失败了。节点使用默认的白色背景绘制。

如何使项目的文本背景透明?

谢谢。

最好的问候。

下面是说明性代码sn-p:

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

【问题讨论】:

  • 您是否尝试将lParam 转换为LPNMTVCUSTOMDRAW 并将clrTextBk 成员设置为CLR_NONE
  • @user1793036:是的,我试过了,背景颜色变成黑色,正如我所料。感谢您尝试提供帮助。最好的问候。
  • 退回白色画笔时会发生什么?返回 (INT_PTR)CreateSolidBrush(RGB(255,255,255));
  • @Eejin:白刷应该去哪里退?

标签: c++ winapi treeview custom-draw


【解决方案1】:

很遗憾,如果不自己绘制这些项目,这将无法轻松实现,抱歉。

事实证明,树视图控件传统上在内部使用ExtTextOut() 函数来绘制项目标题。此函数采用显式标志参数,其中值ETO_OPAQUE 表示“当前的背景颜色应该用于填充矩形”。

因为这个选项是作为一个额外的标志传递的,而不是通过查看当前 GDI 后台模式来确定的,所以您不能在自定义绘制处理程序中使用 SetBkMode() 来解决这个问题。 DC的背景色属性也不支持alpha通道,所以不能只设置为透明。

由于 Common Controls 版本 6.0 和主题窗口装饰,这有点不同,但在这种情况下仍然没有用:控件只调用 DrawThemeBackground()TVP_TREEITEM 部分,其余根据主题处理用过的。例如,我在 Windows 8.1 的默认 Aero 主题中看到有以下条目:

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

那么,有哪些替代方案?

始终可以选择为CDDS_ITEMPREPAINT 事件返回CDRF_SKIPDEFAULT,并自行执行所有显示操作。但是,您甚至需要注意绘制线条、[+] 框、选择和焦点矩形以及其他所有内容。

另一种选择可能是将存储在控件中的标题文本留空,然后将其添加到CDDS_ITEMPOSTPAINT - 即使用TVM_GETITEMRECTwParam=TRUE 来获取文本矩形并在其他所有内容之后在其中绘制真实文本已被控件绘制。但是这种方法也失败了,因为即使对于空文本,也显然绘制了一些小的不透明矩形。您需要先擦除该工件,然后才能继续自己绘制文本。想出一个适用于所有项目状态组合的代码似乎很棘手。

【讨论】:

  • 该死......你所说的一切我之前都尝试过,我同意你的观点,这将是很多工作......暂时赞成。我会等到赏金到期才正式接受,绝望地希望奇迹会发生。最好的问候。
  • 是的,我感受到了你的痛苦——这样的事情应该很简单,对吧?我对现代主题的通用控件如何做到这一点做了一些进一步的研究(答案已更新),但是,结果仍然是一样的......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-26
  • 1970-01-01
  • 1970-01-01
  • 2014-08-21
  • 2012-10-05
  • 1970-01-01
相关资源
最近更新 更多