Heres a C# solution that will fit into a single file and is easy to implement in any project.
By default the advanced graphic options are turned off and can be turned on using properties in the "Glass" section.
I also included a few code optimizations and disposed properly of certain objects within the paint methods, also included double buffering on the control
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
public class GlassPanel : Panel
{
private bool bMouseIsHover = false;
private Bitmap btMousePointer = new Bitmap(32, 32, PixelFormat.Format32bppArgb);
#region "Generic component"
public GlassPanel()
: base()
{
DoubleBuffered = true;
MouseMove += Panel_MouseMove;
MouseLeave += Panel_MouseLeave;
MouseEnter += Panel_MouseEnter;
Paint += Panel_Paint;
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.Opaque, false);
SetStyle(ControlStyles.EnableNotifyMessage, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
BackColor = Color.Transparent;
}
[Browsable(false)]
public bool MouseIsHover
{
get { return bMouseIsHover; }
}
private void Panel_Paint(object sender, PaintEventArgs e)
{
PaintBackgoundSurface(this, e);
PaintBorder(this, e);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
}
#endregion
#region "Mouse Events"
private void Panel_MouseEnter(object sender, System.EventArgs e)
{
bMouseIsHover = true;
CaptureMousePointerImage();
}
private void Panel_MouseLeave(object sender, System.EventArgs e)
{
bMouseIsHover = false;
Invalidate();
}
private void Panel_MouseMove(object sender, MouseEventArgs e)
{
Invalidate();
}
#endregion
#region "Properties"
private bool bMouseReflection = false;
[Category("Glass"), Description("Should the mouse cursor reflects on the glass surface.")]
public bool MouseReflection
{
get { return bMouseReflection; }
set
{
bMouseReflection = value;
Invalidate();
}
}
private int iOpacity = 50;
[Category("Glass"), Description("Sets the opacity of the glass (between 0 [transparent] and 255 [opaque])")]
public int Opacity
{
get { return iOpacity; }
set
{
if (value > 255)
value = 255;
if (value < 0)
value = 0;
iOpacity = value;
Invalidate();
}
}
private Color clGlassColor = Color.WhiteSmoke;
[Category("Glass"), Description("Defines the color of the glass. Among good choices (WhiteSmoke, AliceBlue, MistyRose, AntiqueWhite, Ivory, HoneyDew, Lavender")]
public Color GlassColor
{
get { return clGlassColor; }
set
{
clGlassColor = value;
Invalidate();
}
}
private bool bPaintReflectiveBands = false;
[Category("Glass"), Description("SShould the reflective bands be painted.")]
public bool DoPaintReflectiveBands
{
get { return bPaintReflectiveBands; }
set
{
bPaintReflectiveBands = value;
Invalidate();
}
}
private bool bPaintHorizontalSurface = false;
[Category("Glass"), Description("Should the horisontal surface be painted.")]
public bool DoPaintHorizontalSurface
{
get { return bPaintHorizontalSurface; }
set
{
bPaintHorizontalSurface = value;
Invalidate();
}
}
private bool bPaintGlowSurface = false;
[Category("Glass"), Description("Should the glow surface be painted.")]
public bool DoPaintGlowSuface
{
get { return bPaintGlowSurface; }
set
{
bPaintGlowSurface = value;
Invalidate();
}
}
private bool bCreateReflectiveBands = false;
[Category("Glass"), Description("Should the reflective bands be painted.")]
public bool DoCreateReflectiveBands
{
get { return bCreateReflectiveBands; }
set
{
bCreateReflectiveBands = value;
Invalidate();
}
}
private bool bPaintLightSource = false;
[Category("Glass"), Description("Should the corner light source be painted.")]
public bool DoPaintLightSource
{
get { return bPaintLightSource; }
set
{
bPaintLightSource = value;
Invalidate();
}
}
#endregion
#region "Private Properties"
[Browsable(false)]
public RectangleF EffectiveBounds
{
get { return new RectangleF(ClientRectangle.X + 2, ClientRectangle.Y + 2, ClientRectangle.Width - 4, ClientRectangle.Height - 4); }
}
[Browsable(false)]
public GraphicsPath RoundSurface
{
get { return RoundCorners(EffectiveBounds, (int)Radius); }
}
[Browsable(false)]
public GraphicsPath RoundSurfaceInner
{
get
{
RectangleF rect = EffectiveBounds;
rect.Inflate(-1, -1);
return RoundCorners(rect, (int)Radius);
}
}
[Browsable(false)]
public Region InnerRegion
{
get
{
Region rgInnerRegion = new Region(RoundSurface);
return rgInnerRegion;
}
}
[Browsable(false)]
public Region OuterRegion
{
get
{
Region rgOuterRegion = new Region(RoundSurface);
rgOuterRegion.Xor(ClientRectangle);
return rgOuterRegion;
}
}
private float snRadius = 5;
[Browsable(false)]
public float Radius
{
get { return snRadius; }
set { snRadius = value; }
}
#endregion
#region "Paintings"
private void PaintBackgoundSurface(object sender, PaintEventArgs e)
{
{
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
}
using (SolidBrush brGlass = new SolidBrush(Color.FromArgb(Check(Opacity), GlassColor.R, GlassColor.G, GlassColor.B)))
{
e.Graphics.FillPath(brGlass, RoundSurface);
}
if (DoPaintHorizontalSurface)
{
PaintHorizontalSurface(sender, e);
}
if (DoPaintGlowSuface)
{
PaintGlowSurface(sender, e);
}
if (DoPaintReflectiveBands)
{
PaintReflectiveBands(sender, e);
}
if (DoPaintLightSource)
{
PaintLightSource(sender, e);
}
if (bMouseIsHover)
PaintMouseCursorReflection(sender, e);
}
private void PaintReflectiveBands(object sender, PaintEventArgs e)
{
using (SolidBrush brGlassReflect = new SolidBrush(Color.FromArgb(Check((int)(Opacity * 0.5)), GlassColor.R, GlassColor.G, GlassColor.B)))
{
GraphicsPath grpBand1 = CreateReflectiveBand(0.1f, 0.5f, 0.15f);
GraphicsPath grpBand2 = CreateReflectiveBand(0.4f, 0.8f, 0.1f);
e.Graphics.FillPath(brGlassReflect, grpBand1);
e.Graphics.FillPath(brGlassReflect, grpBand2);
}
}
private void PaintHorizontalSurface(object sender, PaintEventArgs e)
{
using (SolidBrush brGlassDark = new SolidBrush(Color.FromArgb((int)(Opacity * 2.5), DeductMinZero(GlassColor.R, 50), DeductMinZero(GlassColor.G, 50), DeductMinZero(GlassColor.B, 50))))
{
e.Graphics.ExcludeClip(new Rectangle((int)(EffectiveBounds.Left), (int)(EffectiveBounds.Top), (int)(EffectiveBounds.Width), (int)(EffectiveBounds.Height * 0.66f)));
e.Graphics.FillPath(brGlassDark, RoundSurface);
}
e.Graphics.ResetClip();
}
private void PaintGlowSurface(object sender, PaintEventArgs e)
{
using (LinearGradientBrush brGlassDarkLinear = new LinearGradientBrush(ClientRectangle, Color.FromArgb(0, DeductMinZero(GlassColor.R, 50), DeductMinZero(GlassColor.G, 50), DeductMinZero(GlassColor.B, 50)), Color.FromArgb(Check((int)(Opacity * 2.5)), GlassColor.R, GlassColor.G, GlassColor.B), LinearGradientMode.Vertical))
{
e.Graphics.FillPath(brGlassDarkLinear, RoundSurfaceInner);
}
}
private GraphicsPath CreateReflectiveBand(float LeftFactor, float RightFactor, float SizeFactor)
{
GraphicsPath grpBand = new GraphicsPath();
{
grpBand.StartFigure();
grpBand.AddLine(2 + (EffectiveBounds.Width * LeftFactor), 2, 2 + (EffectiveBounds.Width * LeftFactor) + (EffectiveBounds.Width * SizeFactor), 2);
grpBand.AddLine((2 + (EffectiveBounds.Width * LeftFactor)) + (EffectiveBounds.Width * SizeFactor), 2, (2 + (EffectiveBounds.Width * RightFactor)) + (EffectiveBounds.Width * SizeFactor), EffectiveBounds.Top + EffectiveBounds.Height);
grpBand.AddLine((2 + (EffectiveBounds.Width * RightFactor) + (EffectiveBounds.Width * SizeFactor)), 2 + EffectiveBounds.Height, EffectiveBounds.Left + (EffectiveBounds.Width * RightFactor), EffectiveBounds.Top + EffectiveBounds.Height);
grpBand.AddLine(2 + (EffectiveBounds.Width * RightFactor), 2 + EffectiveBounds.Height, 2 + (EffectiveBounds.Width * LeftFactor), 2);
grpBand.CloseFigure();
}
return grpBand;
}
private void PaintLightSource(object sender, PaintEventArgs e)
{
RectangleF rcLight = GetLightBounds(0.75f);
GraphicsPath grpLight = new GraphicsPath();
grpLight.StartFigure();
grpLight.AddEllipse(rcLight);
PathGradientBrush brLight = new PathGradientBrush(grpLight);
brLight.CenterColor = Color.FromArgb(Check(Opacity * 3), 255, 255, 255);
brLight.SurroundColors = new Color[] { Color.FromArgb(0, 255, 255, 255) };
e.Graphics.ExcludeClip(OuterRegion);
e.Graphics.FillEllipse(brLight, rcLight);
e.Graphics.ResetClip();
}
private RectangleF GetLightBounds(float Size)
{
return new RectangleF(2 - ((EffectiveBounds.Height * Size) / 2), 2 - ((EffectiveBounds.Height * Size) / 2), EffectiveBounds.Height * Size, EffectiveBounds.Height * Size);
}
private void PaintBorder(object sender, PaintEventArgs e)
{
e.Graphics.DrawPath(new Pen(Color.FromArgb(200, 255, 255, 255), 0.5f), RoundSurface);
e.Graphics.DrawPath(new Pen(Color.FromArgb(255, 0, 0, 0), 0.5f), RoundSurfaceInner);
}
private void PaintMouseCursorReflection(object sender, PaintEventArgs e)
{
Point ptMouseLocation = this.PointToClient(Cursor.Position);
ptMouseLocation.Offset(-30, -30);
ColorMatrix clrMatrix = null;
clrMatrix = new ColorMatrix(new float[][] {
new float[] {
1,
0,
0,
0,
0
},
new float[] {
0,
1,
0,
0,
0
},
new float[] {
0,
0,
1,
0,
0
},
new float[] {
0,
0,
0,
0.1f,
0
},
new float[] {
0,
0,
0,
0,
1
}
});
using (ImageAttributes imgAttributes = new ImageAttributes())
{
imgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
e.Graphics.ExcludeClip(OuterRegion);
e.Graphics.DrawImage(btMousePointer, new Rectangle(ptMouseLocation.X, ptMouseLocation.Y, 32, 32), 0, 0, 32, 32, GraphicsUnit.Pixel, imgAttributes);
}
e.Graphics.ResetClip();
}
private void CaptureMousePointerImage()
{
Graphics grPointer = Graphics.FromImage(btMousePointer);
grPointer.Clear(Color.Transparent);
Cursor.Current.Draw(grPointer, new Rectangle(0, 0, 32, 32));
}
#endregion
internal int Check(int Value)
{
if (Value > 255)
{
return 255;
}
else if (Value < 0)
{
return 0;
}
else
{
return Value;
}
}
internal Color Darken(Color Color)
{
return Color.FromArgb(Color.A, DeductMinZero(Color.R, 20), DeductMinZero(Color.G, 20), DeductMinZero(Color.B, 20));
}
internal Color Lighten(Color Color)
{
return Color.FromArgb(Color.A, AddMax255(Color.R, 20), AddMax255(Color.G, 20), AddMax255(Color.B, 20));
}
internal int DeductMinZero(int Value, int Deduction)
{
if (Value - Deduction < 0)
{
return 0;
}
else
{
return Value - Deduction;
}
}
internal int AddMax255(int Value, int Addition)
{
if (Value + Addition > 255)
{
return 255;
}
else
{
return Value + Addition;
}
}
internal StringFormat GetStringFormat(ContentAlignment Alignment)
{
StringFormat sfText = new StringFormat();
switch (Alignment)
{
case ContentAlignment.BottomCenter:
case ContentAlignment.MiddleCenter:
case ContentAlignment.TopCenter:
sfText.Alignment = StringAlignment.Center;
break;
case ContentAlignment.BottomLeft:
case ContentAlignment.MiddleLeft:
case ContentAlignment.TopLeft:
sfText.Alignment = StringAlignment.Near;
break;
case ContentAlignment.BottomRight:
case ContentAlignment.MiddleRight:
case ContentAlignment.TopRight:
sfText.Alignment = StringAlignment.Far;
break;
}
switch (Alignment)
{
case ContentAlignment.BottomCenter:
case ContentAlignment.BottomLeft:
case ContentAlignment.BottomRight:
sfText.LineAlignment = StringAlignment.Far;
break;
case ContentAlignment.MiddleCenter:
case ContentAlignment.MiddleLeft:
case ContentAlignment.MiddleRight:
sfText.LineAlignment = StringAlignment.Center;
break;
case ContentAlignment.TopCenter:
case ContentAlignment.TopLeft:
case ContentAlignment.TopRight:
sfText.LineAlignment = StringAlignment.Near;
break;
}
return sfText;
}
internal string RemoveAmpersand(string Text)
{
return Text.Replace("&", "");
}
internal Point GetImageDrawingPoint(Size ImageSize, ContentAlignment Alignment, Size ControlSize)
{
int iHorizPosition = 0;
int iVertPosition = 0;
switch (Alignment)
{
case ContentAlignment.BottomCenter:
case ContentAlignment.MiddleCenter:
case ContentAlignment.TopCenter:
iHorizPosition = (int)(ControlSize.Width * 0.5 - ImageSize.Width * 0.5);
break;
case ContentAlignment.BottomLeft:
case ContentAlignment.MiddleLeft:
case ContentAlignment.TopLeft:
iHorizPosition = 2;
break;
case ContentAlignment.BottomRight:
case ContentAlignment.MiddleRight:
case ContentAlignment.TopRight:
iHorizPosition = ControlSize.Width - 2 - ImageSize.Width;
break;
}
switch (Alignment)
{
case ContentAlignment.BottomCenter:
case ContentAlignment.BottomLeft:
case ContentAlignment.BottomRight:
iVertPosition = ControlSize.Height - 2 - ImageSize.Height;
break;
case ContentAlignment.MiddleCenter:
case ContentAlignment.MiddleLeft:
case ContentAlignment.MiddleRight:
iVertPosition = (int)(ControlSize.Height * 0.5 - ImageSize.Height * 0.5);
break;
case ContentAlignment.TopCenter:
case ContentAlignment.TopLeft:
case ContentAlignment.TopRight:
iVertPosition = 2;
break;
}
return new Point(iHorizPosition, iVertPosition);
}
internal GraphicsPath RoundCorners(RectangleF Rectangle, int Radius)
{
Corner Corners = Corner.All;
GraphicsPath p = new GraphicsPath();
float x = Rectangle.X;
float y = Rectangle.Y;
float w = Rectangle.Width;
float h = Rectangle.Height;
int r = Radius;
p.StartFigure();
if (Convert.ToBoolean(Corners & Corner.TopLeft))
{
p.AddArc(new RectangleF(x, y, 2 * r, 2 * r), 180, 90);
}
else
{
p.AddLine(new PointF(x, y + r), new PointF(x, y));
p.AddLine(new PointF(x, y), new PointF(x + r, y));
}
p.AddLine(new PointF(x + r, y), new PointF(x + w - r, y));
if (Convert.ToBoolean(Corners & Corner.TopRight))
{
p.AddArc(new RectangleF(x + w - 2 * r, y, 2 * r, 2 * r), 270, 90);
}
else
{
p.AddLine(new PointF(x + w - r, y), new PointF(x + w, y));
p.AddLine(new PointF(x + w, y), new PointF(x + w, y + r));
}
p.AddLine(new PointF(x + w, y + r), new PointF(x + w, y + h - r));
if (Convert.ToBoolean(Corners & Corner.BottomRight))
{
p.AddArc(new RectangleF(x + w - 2 * r, y + h - 2 * r, 2 * r, 2 * r), 0, 90);
}
else
{
p.AddLine(new PointF(x + w, y + h - r), new PointF(x + w, y + h));
p.AddLine(new PointF(x + w, y + h), new PointF(x + w - r, y + h));
}
p.AddLine(new PointF(x + w - r, y + h), new PointF(x + r, y + h));
if (Convert.ToBoolean(Corners & Corner.BottomLeft))
{
p.AddArc(new RectangleF(x, y + h - 2 * r, 2 * r, 2 * r), 90, 90);
}
else
{
p.AddLine(new PointF(x + r, y + h), new PointF(x, y + h));
p.AddLine(new PointF(x, y + h), new PointF(x, y + h - r));
}
p.AddLine(new PointF(x, y + h - r), new PointF(x, y + r));
p.CloseFigure();
return p;
}
[Flags()]
public enum Corner
{
None = 0,
TopLeft = 1,
TopRight = 2,
BottomLeft = 4,
BottomRight = 8,
All = TopLeft | TopRight | BottomLeft | BottomRight,
AllTop = TopLeft | TopRight,
AllLeft = TopLeft | BottomLeft,
AllRight = TopRight | BottomRight,
AllBottom = BottomLeft | BottomRight
}
}
Thanks again to Nick for a great article
Also nick if you could please take this code and zip it in a single file I would appreciate so i can remove this post becuase its very long
Chona1171
Web Developer (C#), Silverlight
|