Click here to Skip to main content
Click here to Skip to main content

A Reflective and Translucent Glass Panel

, 1 Oct 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
Component derived from Panel that acts like a window (glass)

Introduction

This component is the logical suite of the AlphaGradientPanel published here on CodeProject. It replaces the original System.Windows.Form.Panel by a nifty glassy one.

Background

No idea, I wanted to have glass.

Using the Code

The panel has three main properties. 

  • The glass color (GlassColor) which defines the base tint of the glass panel.
  • The glass opacity (Opacity) which defines the opacity of the panel.
  • Whether the mouse cursor is reflected on the panel (MouseReflection).

It is mainly used like any other panel would be used.

Points of Interest

It's far from perfect and you are to have a good graphic card to use it, but the effect is kind of cool.

History 

  • v. 1.0 - October 2008

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Nicolas Wälti
Software Developer (Senior)
Switzerland Switzerland
No Biography provided

Comments and Discussions

 
GeneralGood But Not Working with other controls see details Pinmemberstelios198422-May-13 22:42 
Questioncompact framework compatibility Pinmembermoosavi9124-Jun-12 5:46 
QuestionNot work in Windows 7 PinmemberMember 439692024-Apr-12 19:53 
QuestionCan you please provide a c# version ? PinmemberFailed Noob2-Oct-11 5:47 
QuestionTransparency Problems PinmemberIbsy31-Dec-10 3:32 
GeneralNice atricle PinmemberChona117130-Sep-10 22:24 
GeneralRe: Nice atricle Pinmember(Nick Waelti)11-Oct-10 21:16 
GeneralRe: Nice atricle PinmemberChona117111-Oct-10 22:00 
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();
            //New Rectangle(e.X - 32, e.Y - 32, 64, 64)
        }
 
        #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();
            //top left arc
            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));
            }
 
            //top line
            p.AddLine(new PointF(x + r, y), new PointF(x + w - r, y));
 
            //top right arc
            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));
            }
 
            //right line
            p.AddLine(new PointF(x + w, y + r), new PointF(x + w, y + h - r));
 
            //bottom right arc
            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));
            }
 
            //bottom line
            p.AddLine(new PointF(x + w - r, y + h), new PointF(x + r, y + h));
 
            //bottom left arc
            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));
            }
 
            //left line
            p.AddLine(new PointF(x, y + h - r), new PointF(x, y + r));
 
            //close figure...
            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

GeneralRe: Nice atricle PinmemberFailed Noob2-Oct-11 6:02 
GeneralImplementing the control PinmemberSushilKumar178323-Nov-09 0:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 1 Oct 2008
Article Copyright 2008 by Nicolas Wälti
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid