因此,现在查看了一段时间,我已经阅读了大约 20 种不同的实现,但还没有看到一个可靠的、基于控件的、基于框架的通用解决方案来实现真正透明的控件。
这种可能过于简单的方法根本没有做任何事情,并创建了一个永远不会被使用的例程(InvalidateEx):http: //bytes.com/topic/c-sharp/answers/248836-need-make-user-control-transparent
这似乎暗示了先前的答案是什么:https ://web.archive.org/web/20141227200000/http://bobpowell.net/transcontrols.aspx
但是它使用计时器滴答来执行 InvalidateEx 方法。
这似乎放弃了多层控件并在单个分层面板上处理所有绘图,同时掩盖了标签对象似乎如何实现其自己的透明度: http: //www.codeproject.com/Articles/25048/How-在窗口中使用透明图像和标签
这是一种完全不基于框架的方法: http: //www.codeproject.com/Articles/30135/General-solution-for-transparent-controls
这个答案中接受的解决方案对我来说根本不起作用:透明控制上的透明控制?
我得到的控件是通用的纯色(白色),上面绘制了透明图像。
所以,我开始我自己的实现。
我宁愿不依赖自底向上的 GDI 绘图,即以最父窗体执行所有绘图,我宁愿不对透明位图进行预渲染,我宁愿不从 Forms.Control 以外的其他东西继承这正在执行一些自己的巧妙技巧来缩短透明度。我真的很想深入了解如何在具有完全透明度支持的控制面上绘图。显然,例如标签控件本身就有一个完整的实现,它是如何工作的?
从逻辑上讲,透明控件不能依赖简单的 1 位剪辑区域,需要保持大部分完整。需要正确处理控件的多层,即正确的绘制顺序等,而不会导致无限循环。
第一个也是最常见的建议是:
SetStyle(ControlStyles.SupportsTransparentBackColor, True)
Me.BackColor = Color.Transparent
我理解的第一行是同义词
Protected Overrides ReadOnly Property CreateParams As System.Windows.Forms.CreateParams
Get
Dim result As System.Windows.Forms.CreateParams = MyBase.CreateParams
result.ExStyle = result.ExStyle Or WindowsMessages.WS_EX_TRANSPARENT
Return result
End Get
End Property
根据继承的类,它的行为非常不同。对于 Forms.Control,OnPaintBackground 选择使用父控件的背景颜色清除剪辑矩形。不太聪明。
覆盖和删除基本 OnPaintBackground 调用会导致控件保持“脏”状态,而不会覆盖它下面的内容。使用透明颜色(乐观方法)清除会产生黑色透明像素场,并使控件显示为完全黑色。
从逻辑上讲,这是有道理的,为提高效率而进行的底层控制不会重新绘制他们预期此控制会覆盖的区域。然后表单的该区域永远不会更新并保持表单存在之前的任何内容。在其上绘制透明颜色有点令人困惑,因为这意味着图形缓冲区甚至不包含底层像素,而是实际的空白被替换为黑色透明的东西以使控件显示为黑色。
第一个挑战似乎是处理控件本身重绘时的处理,让所有底层控件在该区域中重绘自身(不会自动使控件本身无效以开始堆栈溢出),然后在底层和最新像素上绘制自身. 我还没有找到一种方法来做到这一点。我最接近的是通过挖掘 .net 代码并找到 ButtonRenderer.DrawParentBackground 方法。这在很大程度上似乎有效,尽管快速测试表明重叠组件的 z 顺序仍未正确处理,底层控件绘制在该控件的顶部。
第二个挑战是当底层控件发生变化时,让控件正确地重绘自身。通过在质询一中断开自动失效,很难通知控件使其自身失效而不使其父项失效。
如果有人完全解决了这个问题,请提供代码,如果没有,请提供一些我如何处理问题的一个或几个部分的经验。
非常感谢。
编辑:
根据 WS_EX_TRANSPARENT 似乎假设了有关 WS_EX_TRANSPARENT 的详细信息- 它实际上做了什么?
研究更新: ButtonRenderer.DrawParentBackground 实际上只是由 Control 本身使用,仅当使用 Application.EnableVisualStyles() 并简单地强制父级的背景绘制。似乎是的同义词
InvokePaintBackground(Parent, e.Graphics)
这将重现父控件的所有背景绘制细节。