Microsoft KB Archive/943454

= WinForms: How to create a control transparent to other controls =

Article ID: 943454

Article Last Modified on 10/5/2007

-

APPLIES TO


 * Microsoft .NET Framework 1.0
 * Microsoft .NET Framework 1.1
 * Microsoft .NET Framework 2.0
 * Microsoft .NET Framework 3.0

-



Source: Microsoft Support



RAPID PUBLISHING
RAPID PUBLISHING ARTICLES PROVIDE INFORMATION DIRECTLY FROM WITHIN THE MICROSOFT SUPPORT ORGANIZATION. THE INFORMATION CONTAINED HEREIN IS CREATED IN RESPONSE TO EMERGING OR UNIQUE TOPICS, OR IS INTENDED SUPPLEMENT OTHER KNOWLEDGE BASE INFORMATION.



Action
When a transparent control covers another control, the Form's background shows through instead of the hidden control.



Result


Cause
Transparent controls in WinForms are transparent relative to their parent, not to other controls. Transparency in WinForms is more akin to camouflage than true transparency. A transparent control doesn’t actually let you see the control behind it through the form. It asks its parent to draw its own background on the &quot;transparent&quot; control. This is why a transparent control shows the form behind it, but covers up any other controls.



Resolution
To implement transparency relative to other controls requires doing the same thing but on a larger scale: instead of just asking the parent to draw on the foreground control’s background, the control needs to ask all controls behind it to draw on its background. This will only work for controls which provide some method to request that they be drawn and will not automatically update when the background control’s image changes.



MoreInformation
Here is sample code to demonstrate drawing the parent and sibling controls onto a bitmap which can be displayed as the background image of the control.

 _

Public Shared Function MapWindowPoints(ByVal hwndFrom As HandleRef, ByVal hwndTo As HandleRef, ByRef lpPoints As POINT,  ByVal cPoints As Integer) As Int32

End Function

 _

Public Structure POINT

Public X As Integer

Public Y As Integer

Public Sub New(ByVal X As Integer, ByVal Y As Integer)

Me.X = X

Me.Y = Y

End Sub

End Structur

Dim backgroundCache As Bitmap

Dim regenerations As Integer = 0

Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)

' First paint our parent's background

If (backgroundCache Is Nothing) Then

regenerations = regenerations + 1

backgroundCache = New Bitmap(Me.Width, Me.Height)

Dim g As Graphics = Graphics.FromImage(backgroundCache)

Dim rectangle As Rectangle = New Rectangle(0, 0, Me.Width, Me.Height)

If (Not Me.Parent Is Nothing) Then

' Offset the graphics origin to match the parent.

Dim p As Point = New Point

p.X = p.Y = 0

MapWindowPoints(New HandleRef(Me, Handle), New HandleRef(Parent, Parent.Handle), p, 1)

'offset the cliprect into parent space

rectangle.Offset(p.X, p.Y)

Dim np As PaintEventArgs = New PaintEventArgs(g, rectangle)

Dim state As GraphicsState = g.Save

Try

g.TranslateTransform(-p.X, -p.Y)

'get the parent to erase our background

InvokePaintBackground(Parent, np)

' Set it up again in case OnPaintBackground screwed it up

g.Restore(state)

state = g.Save

g.TranslateTransform(-p.X, -p.Y)

'tell the parent to paint its foreground

InvokePaint(Parent, np)

Finally

g.Restore(state)

End Try

rectangle.Offset(-p.X, -p.Y)

Else

'For whatever reason, our parent can't paint our background, but we need some kind of background

'since we're transparent.

g.FillRectangle(SystemBrushes.Control, rectangle)

End If

' Then paint our siblings' foreground

Dim sibs As ControlCollection = Me.Parent.Controls

For i As Integer = sibs.Count To 1 Step -1

Dim c As Control = sibs(i - 1)

' We only care about controls behind us

If c.Equals(Me) Then

Exit For

End If

' Don't bother if we don't share space

If (Me.Bounds.IntersectsWith(c.Bounds)) Then

Dim p As Point = New Point

'offset our origin to match the sibling's

p.X = Me.Bounds.X - c.Bounds.X

p.Y = Me.Bounds.Y - c.Bounds.Y

'offset the cliprect into the sibling control's space

rectangle.Offset(p.X, p.Y)

Dim np As PaintEventArgs = New PaintEventArgs(g, rectangle)

Dim state As GraphicsState = g.Save

Try

' save the state so we can undo the change

' for the next go around

state = g.Save

g.TranslateTransform(-p.X, -p.Y)

'tell the control to paint its foreground

InvokePaint(c, np)

Finally

g.Restore(state)

End Try

End If

Next

End If

Dim g2 As Graphics = pevent.Graphics

g2.DrawImage(backgroundCache, 0, 0)

End Sub



DISCLAIMER
MICROSOFT CORPORATION AND/OR ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY, RELIABILITY, OR ACCURACY OF THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN. ALL SUCH INFORMATION AND RELATED GRAPHICS ARE PROVIDED &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND. MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THIS INFORMATION AND RELATED GRAPHICS, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, WORKMANLIKE EFFORT, TITLE AND NON-INFRINGEMENT. YOU SPECIFICALLY AGREE THAT IN NO EVENT SHALL MICROSOFT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, PUNITIVE, INCIDENTAL, SPECIAL, CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF USE, DATA OR PROFITS, ARISING OUT OF OR IN ANY WAY CONNECTED WITH THE USE OF OR INABILITY TO USE THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN, WHETHER BASED ON CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY OR OTHERWISE, EVEN IF MICROSOFT OR ANY OF ITS SUPPLIERS HAS BEEN ADVISED OF THE POSSIBILITY OF DAMAGES.

Keywords: kbnomt kbrapidpub KB943454

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.