What is a general solution to creating a transparent control?

前端 未结 2 590
时光说笑
时光说笑 2021-01-12 23:48

So having looked this up for a while now, I have read probably twenty different implementations but have not yet seen a solid, control-based, framework-based general solutio

相关标签:
2条回答
  • 2021-01-13 00:06

    I have created the required general transparency control, the solution was a detailed breakdown of the control and all of its siblings in the parent, and preparing a recursive drawing routine on the OnPaintBackground() method relying on the InvokePaint() and InvokePaintBackground() methods. By defining successively smaller clips and intersecting with lower controls, this method minimises drawing overhead.

    • The complete control includes a method of detecting and responding to sibling controls' Invalidate methods, efficiently drawing the stack of transparent controls and effectively allowing full alpha channel overlays on animated underlying controls.

    • The control can be interleaved with all permutations of child and parent controls while giving visually accurate transparency.

    • Hit testing has not been considered in the control.

    • This control will not overdraw controls whose drawing is not performed during paint events. This is a big limitation.

    • To use the control one simply inherits from the base and overrides the OnPaint method to perform custom drawing. It is also possible to override the OnPaintBackground method so long as a call to the base method is called first.

    Finally, if anyone would like the full code including invalidation handling, let me know. If you have a solution to system drawn components let me know that too. Also if you have a more trivial solution that implies I wasted a bunch of time on this, I wouldn't be upset about receiving that either!

    enter image description here

    An excerpt of the control on the OnPaintBackground method is presented:

    ''' <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
    
    0 讨论(0)
  • 2021-01-13 00:19
    Me.Visible = False
    

    OR

    Me.Opacity = 0
    

    OR

    Me.Hide()
    
    0 讨论(0)
提交回复
热议问题