gpt4 book ai didi

vb.net - 创建透明控件的一般解决方案是什么?

转载 作者:行者123 更新时间:2023-12-04 15:46:38 27 4
gpt4 key购买 nike

因此,经过一段时间的研究,我可能已经阅读了二十种不同的实现,但是还没有看到一个可靠的,基于控件,基于框架的通用解决方案来实现真正透明的控件。
这种可能过于简化的方法根本不执行任何操作,并创建了一个永远不会使用的例程(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-to-Use-Transparent-Images-and-Labels-in-Window
这是一个完全基于非框架的方法:http://www.codeproject.com/Articles/30135/General-solution-for-transparent-controls
此答案中可接受的解决方案对我不起作用:Transparent Control on Transparent control?
我得到的控件是通用纯色(白色),上面绘制了透明图像。
因此,我从我自己的实现开始。
我宁愿不依赖于自下而上的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 - What does it actually do?关于WS_EX_TRANSPARENT的假定详细信息
研究更新: ButtonRenderer.DrawParentBackground实际上仅由Control本身使用,仅当使用Application.EnableVisualStyles()且仅强制父对象的背景绘制时才使用。它似乎是的同义词
InvokePaintBackground(Parent, e.Graphics)
它将重现父控件的所有背景绘制的细节。

最佳答案

我已经创建了所需的常规透明度控件,解决方案是该控件及其父级中所有同级控件的详细分割,并依靠InvokePaint()和InvokePaintBackground()方法在OnPaintBackground()方法上准备递归绘图例程。通过连续定义较小的剪辑并与较低的控件相交,此方法可以最大程度地减少绘图开销。

  • 完整的控件包括一种检测并响应同级控件的Invalidate方法的方法,可以有效地绘制透明控件的堆栈,并可以有效地在动画基础控件上覆盖完整的Alpha channel 。
  • 控件可以与子控件和父控件的所有排列交错,同时提供视觉上准确的透明度。
  • 控件中未考虑 HitTest 。
  • 此控件不会覆盖在绘制事件期间未执行绘制的控件。这是一个很大的限制。
  • 要使用该控件,只需从基类继承并覆盖OnPaint方法即可执行自定义绘制。只要首先调用基本方法,也可以覆盖OnPaintBackground方法。

  • 最后,如果有人想要完整的代码(包括无效处理),请告诉我。如果您对系统绘制的组件有解决方案,请告诉我。另外,如果您有一个更琐碎的解决方案,这意味着我在此上浪费了很多时间,那么我也不会为收到该消息而感到沮丧!

    呈现了OnPaintBackground方法的控件摘录:
    ''' <summary>
    ''' Recursively paint all underlying controls in their relevant regions, stacking drawing operations as necessary.
    ''' </summary>
    ''' <param name="pevent"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnPaintBackground(pevent As System.Windows.Forms.PaintEventArgs)
    'Store clip and transform for reversion
    Dim initialClip As Region = pevent.Graphics.Clip
    Dim initialTransform As Drawing2D.Matrix = pevent.Graphics.Transform

    'Develop list of underlying controls
    Dim submarinedControls As New List(Of Control)
    For Each Control As Control In m_Siblings
    If Control.Visible AndAlso Above(Control) AndAlso Me.ClientRectangle.IntersectsWith(Control.RelativeClientRectangle(Me)) Then submarinedControls.Add(Control)
    Next

    'Prepare clip for parent draw
    Dim parentClip As System.Drawing.Region = New System.Drawing.Region(initialClip.GetRegionData)
    For Each Control As Control In submarinedControls
    parentClip.Exclude(Control.RelativeClientRectangle(Me))
    Next
    pevent.Graphics.Clip = parentClip

    'Evaluate control relationship to parent, temporarily adjusting transformation for parent redraw. This translation must be relative since the incoming graphics may already have a meaningful transform applied.
    Dim translation As Point = Parent.RelationTo(Me)
    pevent.Graphics.Transform = New Drawing2D.Matrix(1, 0, 0, 1, initialTransform.OffsetX + translation.X, initialTransform.OffsetY + translation.Y)

    'Fully draw parent background
    InvokePaintBackground(Parent, pevent)
    InvokePaint(Parent, pevent)

    'Reset transform for sibling drawing
    pevent.Graphics.Transform = initialTransform

    'Develop initial clip of submarined siblings
    Dim siblingClip As System.Drawing.Region = New System.Drawing.Region(initialClip.GetRegionData)
    siblingClip.Exclude(parentClip)

    For Each Control As Control In submarinedControls
    'Define relative position of submarined sibling to self
    translation = Control.RelationTo(Me)

    'Define and apply clip *before* transformation
    Dim intersectionClip As New Region(Control.RelativeClientRectangle(Me))
    intersectionClip.Intersect(siblingClip)
    pevent.Graphics.Clip = intersectionClip

    'Apply transformation
    pevent.Graphics.Transform = New Drawing2D.Matrix(1, 0, 0, 1, initialTransform.OffsetX + translation.X, initialTransform.OffsetY + translation.Y)

    'Raise sibling control's paint events
    InvokePaintBackground(Control, pevent)
    InvokePaint(Control, pevent)

    'Revert transformation and exclude region
    pevent.Graphics.Transform = initialTransform
    siblingClip.Exclude(intersectionClip)
    Next

    'Revert transform and clip to pre-drawing state
    pevent.Graphics.Transform = initialTransform
    pevent.Graphics.Clip = initialClip
    End Sub

    关于vb.net - 创建透明控件的一般解决方案是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11971267/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com