Making a Control Transparent

Making a control transparent

This is my special Control which contains an opacity property, it 100% works:

using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;

public class TranspCtrl : Control
{
public bool drag = false;
public bool enab = false;
private int m_opacity = 100;

private int alpha;
public TranspCtrl()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.Opaque, true);
this.BackColor = Color.Transparent;
}

public int Opacity
{
get
{
if (m_opacity > 100)
{
m_opacity = 100;
}
else if (m_opacity < 1)
{
m_opacity = 1;
}
return this.m_opacity;
}
set
{
this.m_opacity = value;
if (this.Parent != null)
{
Parent.Invalidate(this.Bounds, true);
}
}
}

protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | 0x20;
return cp;
}
}

protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Rectangle bounds = new Rectangle(0, 0, this.Width - 1, this.Height - 1);

Color frmColor = this.Parent.BackColor;
Brush bckColor = default(Brush);

alpha = (m_opacity * 255) / 100;

if (drag)
{
Color dragBckColor = default(Color);

if (BackColor != Color.Transparent)
{
int Rb = BackColor.R * alpha / 255 + frmColor.R * (255 - alpha) / 255;
int Gb = BackColor.G * alpha / 255 + frmColor.G * (255 - alpha) / 255;
int Bb = BackColor.B * alpha / 255 + frmColor.B * (255 - alpha) / 255;
dragBckColor = Color.FromArgb(Rb, Gb, Bb);
}
else
{
dragBckColor = frmColor;
}

alpha = 255;
bckColor = new SolidBrush(Color.FromArgb(alpha, dragBckColor));
}
else
{
bckColor = new SolidBrush(Color.FromArgb(alpha, this.BackColor));
}

if (this.BackColor != Color.Transparent | drag)
{
g.FillRectangle(bckColor, bounds);
}

bckColor.Dispose();
g.Dispose();
base.OnPaint(e);
}

protected override void OnBackColorChanged(EventArgs e)
{
if (this.Parent != null)
{
Parent.Invalidate(this.Bounds, true);
}
base.OnBackColorChanged(e);
}

protected override void OnParentBackColorChanged(EventArgs e)
{
this.Invalidate();
base.OnParentBackColorChanged(e);
}
}

How to create a transparent control which works when on top of other controls?

I decided to simply paint the parent under my child controls manually. Here is a good article.

how to make user controls transparent

After some searches on the internet I found this pearl:

Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
' Make background transparent
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H20
Return cp
End Get
End Property

Protected Overrides Sub OnPaintBackground(e As PaintEventArgs)
'' call MyBase.OnPaintBackground(e) only if the backColor is not Color.Transparent
If Me.BackColor <> Color.Transparent Then
MyBase.OnPaintBackground(e)
End If
End Sub

I've tested it and it seems to be working fine.

How to make a UserControls BackColor transparent in C#?

UserControl already supports this, its ControlStyles.SupportsTransparentBackColor style flag is already turned on. All you have to do is set the BackColor property to Color.Transparent.

Next thing you have to keep in mind in that this transparency is simulated, it is done by asking the Parent of the control to draw itself to produce the background. So what is important is that you get the Parent set correctly. That's a bit tricky to do if the parent is not a container control. Like a PictureBox. The designer will make the Form the parent so you will see the form's background, not the picture box. You'll need to fix that in code, edit the form constructor and make it look similar to this:

var pos = this.PointToScreen(userControl11.Location);
userControl11.Parent = pictureBox1;
userControl11.Location = pictureBox1.PointToClient(pos);

What is a general solution to creating a transparent control?

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!

Sample Image

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

Make a control transparent

Some components have the transparent property. In others you can choose 'none' as the color property. It differs from component to component, but not all components can be made transparent by changing a property.

You should try googling Delphi transparent components, there are downloadable components and tricks you can do to make existing components transparent.



Related Topics



Leave a reply



Submit