Reputation: 2579
I use C#, VisualStudio 2010 and I created a custom UserControl for a Windows Forms application. They don't have much behavior apart from displaying themselves and allowing themselves to be dragged elsewhere. However they are circular in shape and I cannot display them correctly when they overlap on the corners.
Here is my code for painting them on the screen:
public void Circle_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.FillEllipse(brushForOuterCircle, 0, 0, Width, Height);
g.FillEllipse(brushForInnerCircle, lineWidth, lineWidth, Width - 2*lineWidth, Height - 2*lineWidth);
if(!textLocation.HasValue)
{
SizeF m = g.MeasureString(text, textFont);
textLocation = new PointF((float)((Width - m.Width)/2.0), (float)((Height - m.Height)/2.0));
}
g.DrawString(text, textFont, brushForText, textLocation.Value);
}
Here is an example of incorrect display, the southeast part of the AB circle does not display because CD overrides that area.
How should I prevent that, is there a way to tell the UserControl "you are transparent by default; any portion I don't draw onto should remain so" ?
Upvotes: 2
Views: 2514
Reputation: 2056
You should also set the region so that it ignores mouse clicks for the area that is supposed to be transparent. Take a look at the following control as an example. It's a control that paints a circle. I set the Region to an Ellipse causing WinForms to not paint the area outside of the circle. By setting the region it also knows to ignore mouse clicks on the area outside of the region.
using System;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsApplication1
{
public class RoundControl : Control
{
private readonly GraphicsPath _path;
public RoundControl()
{
_path = new GraphicsPath();
}
protected override void OnResize(EventArgs e)
{
_path.Reset();
_path.AddEllipse(ClientRectangle);
Invalidate(Region);
Region = new Region(_path);
base.OnResize(e);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_path.Dispose();
}
base.Dispose(disposing);
}
protected override void OnPaint(PaintEventArgs e)
{
using (Pen borderPen = new Pen(ForeColor, 8))
{
e.Graphics.DrawEllipse(borderPen, ClientRectangle);
}
base.OnPaint(e);
}
}
}
Upvotes: 1
Reputation: 62246
Try to:
setup on your user control first WS_EX_COMPOSITED extended style, by overriding
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; // add this
return cp;
}
}
after do not paint anything in background by
protected override void OnPaintBackground(PaintEventArgs e)
{
// leave this empty
}
and finally in Paint
draw your shape.
Should work.
Upvotes: 3
Reputation: 3499
Try this. Create a TransparencyControl as suggested here: Transparent images with C# WinForms
using System;
using System.Windows.Forms;
using System.Drawing;
public class TransparentControl : Control
{
private readonly Timer refresher;
private Image _image;
public TransparentControl()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
BackColor = Color.Transparent;
refresher = new Timer();
refresher.Tick += TimerOnTick;
refresher.Interval = 50;
refresher.Enabled = true;
refresher.Start();
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
protected override void OnMove(EventArgs e)
{
RecreateHandle();
}
protected override void OnPaint(PaintEventArgs e)
{
if (_image != null)
{
e.Graphics.DrawImage(_image, (Width / 2) - (_image.Width / 2), (Height / 2) - (_image.Height / 2));
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//Do not paint background
}
//Hack
public void Redraw()
{
RecreateHandle();
}
private void TimerOnTick(object source, EventArgs e)
{
RecreateHandle();
refresher.Stop();
}
public Image Image
{
get
{
return _image;
}
set
{
_image = value;
RecreateHandle();
}
}
}
Upvotes: 1