How to Make Two Transparent Layer with C#

How to make two transparent layer with c#?

If you need a control support transparency, you should override painting of the control and draw the control in this order:

  • Draw all controls in the same container which are under your control (based on z-index) on a bitmap.
  • Then draw that bitmap on graphics of your control.
  • At last draw content of your control.
  • Also the BackColor of your control should be Color.Transparent.

Here is the result of creating TransparentLabel and TransparentPictureBox controls. In the below image, there is label, image, label, image and then label in order and as you can see picture boxes and labels has been rendered having transparent background and respecting the z-index:

Sample Image

Transparent Label

class TransparentLabel : Label
{
public TransparentLabel()
{
this.BackColor = Color.Transparent;
}
protected override void OnPaint(PaintEventArgs e)
{
if (Parent != null && this.BackColor == Color.Transparent)
{
using (var bmp = new Bitmap(Parent.Width, Parent.Height))
{
Parent.Controls.Cast<Control>()
.Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this))
.Where(c => c.Bounds.IntersectsWith(this.Bounds))
.OrderByDescending(c => Parent.Controls.GetChildIndex(c))
.ToList()
.ForEach(c => c.DrawToBitmap(bmp, c.Bounds));

e.Graphics.DrawImage(bmp, -Left, -Top);

}
}
base.OnPaint(e);
}
}

Transparent PictureBox

class TransparentPictureBox : PictureBox
{
public TransparentPictureBox()
{
this.BackColor = Color.Transparent;
}
protected override void OnPaint(PaintEventArgs e)
{
if (Parent != null && this.BackColor==Color.Transparent)
{
using (var bmp = new Bitmap(Parent.Width, Parent.Height))
{
Parent.Controls.Cast<Control>()
.Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this))
.Where(c => c.Bounds.IntersectsWith(this.Bounds))
.OrderByDescending(c => Parent.Controls.GetChildIndex(c))
.ToList()
.ForEach(c => c.DrawToBitmap(bmp, c.Bounds));

e.Graphics.DrawImage(bmp, -Left, -Top);

}
}
base.OnPaint(e);
}
}

Make Picture boxes transparent, each overlapping the other with a corner?

Transparency in winforms is kind of misleading, since it's not really transparency.

Winforms controls mimic transparency by painting the part of their parent control they would hide instead of their own background.

However, they will not paint the other controls that might be partially covered by them.

This is the reason your top most picture boxes hides your big picture box.

You can overcome this by creating a custom control that inherits from PictureBox and override its OnPaintBackground method (taken, with slight adjustments, from this code project article):

protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
Graphics g = e.Graphics;

if (this.Parent != null)
{
var index = Parent.Controls.GetChildIndex(this);
for (var i = Parent.Controls.Count - 1; i > index; i--)
{
var c = Parent.Controls[i];
if (c.Bounds.IntersectsWith(Bounds) && c.Visible)
{
using (var bmp = new Bitmap(c.Width, c.Height, g))
{
c.DrawToBitmap(bmp, c.ClientRectangle);
g.TranslateTransform(c.Left - Left, c.Top - Top);
g.DrawImageUnscaled(bmp, Point.Empty);
g.TranslateTransform(Left - c.Left, Top - c.Top);
}
}
}
}
}

Microsoft have published a Knowledge base article to solve this problem a long time ago, however it's a bit out-dated and it's code sample is in VB.Net.

Another option is to paint the images yourself, without picture boxes to hold them, by using Graphics.DrawImage method.

The best place to do it is probably in the OnPaint method of the form.

How could I position multiple transparent PNGs onto a JPG using c# and asp.net?

Here's some code i use (modified to show the principle):

private void ProcessPhoto()
{

System.Drawing.Image imgThumb = System.Drawing.Image.FromFile("some.jpg");

// 43w, 35h = offset in frame

System.Drawing.Image imgFrame = System.Drawing.Image.FromFile("transparent_something.png");

Bitmap bmImage = new Bitmap(imgThumb);
bmImage.SetResolution(72, 72);
Graphics gFrame = Graphics.FromImage(imgFrame);
gFrame.DrawImage(bmImage, new Point(38, 44)); // offset point of where you want to draw

gFrame.Dispose();

SavePhoto(imgFrame, "dest.png");

imgFrame.Dispose();
imgThumb.Dispose();

}

private void SavePhoto(System.Drawing.Image img, string fileName)
{
string ext = Path.GetExtension(fileName);
fileName = fileName.Replace(ext, ".png");

img.Save(fileName, GetImageEncoder("PNG"), null);
}

Edit:
Read all about the Graphics class here

Add additional half-transparent layer on picturebox

The code would be similar to this:

private void pictureBox1_Paint (object sender, PaintEventArgs e)
{
using (SolidBrush b = new SolidBrush(Color.FromArgb(128, Color.White))
{
e.Graphics.FillRectangle (b, 0, 0, pictureBox1.Width, pictureBox1.Height);
}

However, the code above simply using a single color brush whose opactity is set to 128. There are other brush classes available, such as LinearGradientBrush, TextureBrush, PAthGradientBrush and HatchBrush.

Recommendation
To paint custom effects like you want to (for a button pressed state), a recommended approach would be to generate pre-rendered images that you can create either at runtime of your application or using an external program such as Adobe Photoshop and then save these images.

Then the painting code would simply take the image that represents the current state of your "button" and draw that image in the overriden pictureBox1_Paint method.

This technique results in better graphics painting performance as opposed to simply repainting the same states at different state-change times in the application.

Combining two semi-transparent ellipses

edit: Sorry, there were a few errors with the properties of the various elements. This is tested:

Create a Path and put as Path.Data a GeometryGroup that has the two EllipseGeometries as child elements. Set GeometryGroup.FillRule to "EvenOdd" so that the area that both ellipses cover is not filled, and set "Fill" to the color you want the ellipses to have (here: AliceBlue).

Put that Path into a Control with "Background" property, like Border, and set that Background to the color you want the area both ellipses are covering to be (here: yellow).

Then you set Clip to the same GeometryGroup with FillRule set to "Nonzero" to prevent the area around the ellipses to also be painted with the background color.

        <Border Background="Yellow">
<Path Fill="AliceBlue" Stroke="Black" StrokeThickness="4">
<Path.Data>
<GeometryGroup FillRule="EvenOdd">
<EllipseGeometry Center="100,100" RadiusX="40" RadiusY="80" />
<EllipseGeometry Center="100,100" RadiusX="80" RadiusY="40" />
</GeometryGroup>
</Path.Data>
</Path>
<Border.Clip>
<GeometryGroup FillRule="Nonzero">
<EllipseGeometry Center="100,100" RadiusX="40" RadiusY="80" />
<EllipseGeometry Center="100,100" RadiusX="80" RadiusY="40" />
</GeometryGroup>
</Border.Clip>
</Border>

If you need both ellipses to be painted in different colors use two Border and Path objects, use the same GeometryGroup with "EvenOdd" and set each of Border.Clip to one EllipseGeometry object.

If you need a more detailed definition use a PathGeometry instead of GeometryGroup and define the area with ArcSegments.

How to layer one window on top of another with transparency(Overlay) or how to do aplha-blending on two windows using directx?

Finally I found an answer myself. Further research lead me to This,This thread which was exactly what i was looking for. This might be useful to someone else and might save a lot of head banging on research.



Related Topics



Leave a reply



Submit