using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; using System.Drawing.Text; using PushButtonState = System.Windows.Forms.VisualStyles.PushButtonState; namespace HotelPms.Share.Windows.Component { /// /// Represents a glass button control. /// [ToolboxBitmap(typeof(GlassButton)), ToolboxItem(true), ToolboxItemFilter("System.Windows.Forms"), Description("Raises an event when the user clicks it.")] public partial class GlassButton : Button { #region " Constructors " /// /// Initializes a new instance of the class. /// public GlassButton() { InitializeComponent(); timer.Interval = animationLength / framesCount; base.BackColor = Color.Transparent; BackColor = Color.Black; ForeColor = Color.White; OuterBorderColor = Color.White; InnerBorderColor = Color.Black; ShineColor = Color.White; GlowColor = Color.FromArgb(-7488001);//unchecked((int)(0xFF8DBDFF))); SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true); SetStyle(ControlStyles.Opaque, false); } #endregion #region " Fields and Properties " private Color backColor; /// /// Gets or sets the background color of the control. /// /// A value representing the background color. [DefaultValue(typeof(Color), "Black")] public virtual new Color BackColor { get { return backColor; } set { if (!backColor.Equals(value)) { backColor = value; UseVisualStyleBackColor = false; CreateFrames(); OnBackColorChanged(EventArgs.Empty); } } } /// /// Gets or sets the foreground color of the control. /// /// The foreground of the control. [DefaultValue(typeof(Color), "White")] public virtual new Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } } private Color innerBorderColor; /// /// Gets or sets the inner border color of the control. /// /// A value representing the color of the inner border. [DefaultValue(typeof(Color), "Black"), Category("Appearance"), Description("The inner border color of the control.")] public virtual Color InnerBorderColor { get { return innerBorderColor; } set { if (innerBorderColor != value) { innerBorderColor = value; CreateFrames(); if (IsHandleCreated) { Invalidate(); } OnInnerBorderColorChanged(EventArgs.Empty); } } } private Color outerBorderColor; /// /// Gets or sets the outer border color of the control. /// /// A value representing the color of the outer border. [DefaultValue(typeof(Color), "White"), Category("Appearance"), Description("The outer border color of the control.")] public virtual Color OuterBorderColor { get { return outerBorderColor; } set { if (outerBorderColor != value) { outerBorderColor = value; CreateFrames(); if (IsHandleCreated) { Invalidate(); } OnOuterBorderColorChanged(EventArgs.Empty); } } } private Color shineColor; /// /// Gets or sets the shine color of the control. /// /// A value representing the shine color. [DefaultValue(typeof(Color), "White"), Category("Appearance"), Description("The shine color of the control.")] public virtual Color ShineColor { get { return shineColor; } set { if (shineColor != value) { shineColor = value; CreateFrames(); if (IsHandleCreated) { Invalidate(); } OnShineColorChanged(EventArgs.Empty); } } } private Color glowColor; /// /// Gets or sets the glow color of the control. /// /// A value representing the glow color. [DefaultValue(typeof(Color), "255,141,189,255"), Category("Appearance"), Description("The glow color of the control.")] public virtual Color GlowColor { get { return glowColor; } set { if (glowColor != value) { glowColor = value; CreateFrames(); if (IsHandleCreated) { Invalidate(); } OnGlowColorChanged(EventArgs.Empty); } } } private bool isHovered; private bool isFocused; private bool isFocusedByKey; private bool isKeyDown; private bool isMouseDown; private bool isPressed { get { return isKeyDown || (isMouseDown && isHovered); } } /// /// Gets the state of the button control. /// /// The state of the button control. [Browsable(false)] public PushButtonState State { get { if (!Enabled) { return PushButtonState.Disabled; } if (isPressed) { return PushButtonState.Pressed; } if (isHovered) { return PushButtonState.Hot; } if (isFocused || IsDefault) { return PushButtonState.Default; } return PushButtonState.Normal; } } #endregion #region " Events " /// Occurs when the value of the property changes. [Description("Event raised when the value of the InnerBorderColor property is changed."), Category("Property Changed")] public event EventHandler InnerBorderColorChanged; /// /// Raises the event. /// /// An that contains the event data. protected virtual void OnInnerBorderColorChanged(EventArgs e) { if (InnerBorderColorChanged != null) { InnerBorderColorChanged(this, e); } } /// Occurs when the value of the property changes. [Description("Event raised when the value of the OuterBorderColor property is changed."), Category("Property Changed")] public event EventHandler OuterBorderColorChanged; /// /// Raises the event. /// /// An that contains the event data. protected virtual void OnOuterBorderColorChanged(EventArgs e) { if (OuterBorderColorChanged != null) { OuterBorderColorChanged(this, e); } } /// Occurs when the value of the property changes. [Description("Event raised when the value of the ShineColor property is changed."), Category("Property Changed")] public event EventHandler ShineColorChanged; /// /// Raises the event. /// /// An that contains the event data. protected virtual void OnShineColorChanged(EventArgs e) { if (ShineColorChanged != null) { ShineColorChanged(this, e); } } /// Occurs when the value of the property changes. [Description("Event raised when the value of the GlowColor property is changed."), Category("Property Changed")] public event EventHandler GlowColorChanged; /// /// Raises the event. /// /// An that contains the event data. protected virtual void OnGlowColorChanged(EventArgs e) { if (GlowColorChanged != null) { InnerBorderColorChanged(this, e); } } #endregion #region " Overrided Methods " /// /// Raises the event. /// /// An that contains the event data. protected override void OnSizeChanged(EventArgs e) { CreateFrames(); base.OnSizeChanged(e); } /// /// Raises the event. /// /// The instance containing the event data. protected override void OnClick(EventArgs e) { isKeyDown = isMouseDown = false; base.OnClick(e); } /// /// Raises the event. /// /// An that contains the event data. protected override void OnEnter(EventArgs e) { isFocused = isFocusedByKey = true; base.OnEnter(e); } /// /// Raises the event. /// /// An that contains the event data. protected override void OnLeave(EventArgs e) { base.OnLeave(e); isFocused = isFocusedByKey = isKeyDown = isMouseDown = false; Invalidate(); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnKeyDown(KeyEventArgs kevent) { if (kevent.KeyCode == Keys.Space) { isKeyDown = true; Invalidate(); } base.OnKeyDown(kevent); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnKeyUp(KeyEventArgs kevent) { if (isKeyDown && kevent.KeyCode == Keys.Space) { isKeyDown = false; Invalidate(); } base.OnKeyUp(kevent); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnMouseDown(MouseEventArgs e) { if (!isMouseDown && e.Button == MouseButtons.Left) { isMouseDown = true; isFocusedByKey = false; Invalidate(); } base.OnMouseDown(e); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnMouseUp(MouseEventArgs e) { if (isMouseDown) { isMouseDown = false; Invalidate(); } base.OnMouseUp(e); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnMouseMove(MouseEventArgs mevent) { base.OnMouseMove(mevent); if (mevent.Button != MouseButtons.None) { if (!ClientRectangle.Contains(mevent.X, mevent.Y)) { if (isHovered) { isHovered = false; Invalidate(); } } else if (!isHovered) { isHovered = true; Invalidate(); } } } /// /// Raises the event. /// /// The instance containing the event data. protected override void OnMouseEnter(EventArgs e) { isHovered = true; FadeIn(); Invalidate(); base.OnMouseEnter(e); } /// /// Raises the event. /// /// The instance containing the event data. protected override void OnMouseLeave(EventArgs e) { isHovered = false; FadeOut(); Invalidate(); base.OnMouseLeave(e); } #endregion #region " Painting " /// /// Raises the event. /// /// A that contains the event data. protected override void OnPaint(PaintEventArgs pevent) { DrawButtonBackgroundFromBuffer(pevent.Graphics); DrawForegroundFromButton(pevent); DrawButtonForeground(pevent.Graphics); } private void DrawButtonBackgroundFromBuffer(Graphics graphics) { int frame; if (!Enabled) { frame = FRAME_DISABLED; } else if (isPressed) { frame = FRAME_PRESSED; } else if (!isAnimating && currentFrame == 0) { frame = FRAME_NORMAL; } else { if (!HasAnimationFrames) { CreateFrames(true); } frame = FRAME_ANIMATED + currentFrame; } if (frames == null) { CreateFrames(); } graphics.DrawImage(frames[frame], Point.Empty); } public Image CreateBackgroundFrame(bool pressed, bool hovered, bool animating, bool enabled, float glowOpacity) { Rectangle rect = ClientRectangle; if (rect.Width <= 0) { rect.Width = 1; } if (rect.Height <= 0) { rect.Height = 1; } Image img = new Bitmap(rect.Width, rect.Height); using (Graphics g = Graphics.FromImage(img)) { g.Clear(Color.Transparent); DrawButtonBackground(g, rect, pressed, hovered, animating, enabled, outerBorderColor, backColor, glowColor, shineColor, innerBorderColor, glowOpacity); } return img; } private static void DrawButtonBackground(Graphics g, Rectangle rectangle, bool pressed, bool hovered, bool animating, bool enabled, Color outerBorderColor, Color backColor, Color glowColor, Color shineColor, Color innerBorderColor, float glowOpacity) { SmoothingMode sm = g.SmoothingMode; g.SmoothingMode = SmoothingMode.AntiAlias; #region " white border " Rectangle rect = rectangle; rect.Width--; rect.Height--; using (GraphicsPath bw = CreateRoundRectangle(rect, 4)) { using (Pen p = new Pen(outerBorderColor)) { g.DrawPath(p, bw); } } #endregion rect.X++; rect.Y++; rect.Width -= 2; rect.Height -= 2; Rectangle rect2 = rect; rect2.Height >>= 1; #region " content " using (GraphicsPath bb = CreateRoundRectangle(rect, 2)) { int opacity = pressed ? 0xcc : 0x7f; using (Brush br = new SolidBrush(Color.FromArgb(opacity, backColor))) { g.FillPath(br, bb); } } #endregion #region " glow " if ((hovered || animating) && !pressed) { using (GraphicsPath clip = CreateRoundRectangle(rect, 2)) { g.SetClip(clip, CombineMode.Intersect); using (GraphicsPath brad = CreateBottomRadialPath(rect)) { using (PathGradientBrush pgr = new PathGradientBrush(brad)) { unchecked { int opacity = (int)(0xB2 * glowOpacity + .5f); RectangleF bounds = brad.GetBounds(); pgr.CenterPoint = new PointF((bounds.Left + bounds.Right) / 2f, (bounds.Top + bounds.Bottom) / 2f); pgr.CenterColor = Color.FromArgb(opacity, glowColor); pgr.SurroundColors = new Color[] { Color.FromArgb(0, glowColor) }; } g.FillPath(pgr, brad); } } g.ResetClip(); } } #endregion #region " shine " if (rect2.Width > 0 && rect2.Height > 0) { rect2.Height++; using (GraphicsPath bh = CreateTopRoundRectangle(rect2, 2)) { rect2.Height++; int opacity = 0x99; if (pressed | !enabled) { opacity = (int)(.4f * opacity + .5f); } using (LinearGradientBrush br = new LinearGradientBrush(rect2, Color.FromArgb(opacity, shineColor), Color.FromArgb(opacity / 3, shineColor), LinearGradientMode.Vertical)) { g.FillPath(br, bh); } } rect2.Height -= 2; } #endregion #region " black border " using (GraphicsPath bb = CreateRoundRectangle(rect, 3)) { using (Pen p = new Pen(innerBorderColor)) { g.DrawPath(p, bb); } } #endregion g.SmoothingMode = sm; } private void DrawButtonForeground(Graphics g) { if (Focused && ShowFocusCues) { Rectangle rect = ClientRectangle; rect.Inflate(-4, -4); ControlPaint.DrawFocusRectangle(g, rect); } } private Button imageButton; private void DrawForegroundFromButton(PaintEventArgs pevent) { if (imageButton == null) { imageButton = new Button(); imageButton.Parent = new TransparentControl(); imageButton.BackColor = Color.Transparent; imageButton.FlatAppearance.BorderSize = 0; imageButton.FlatStyle = FlatStyle.Flat; } imageButton.AutoEllipsis = AutoEllipsis; if (Enabled) { imageButton.ForeColor = ForeColor; } else { imageButton.ForeColor = Color.FromArgb((3*ForeColor.R + backColor.R) >> 2, (3*ForeColor.G + backColor.G) >> 2, (3*ForeColor.B + backColor.B) >> 2); } imageButton.Font = Font; imageButton.RightToLeft = RightToLeft; imageButton.Image = Image; imageButton.ImageAlign = ImageAlign; imageButton.ImageIndex = ImageIndex; imageButton.ImageKey = ImageKey; imageButton.ImageList = ImageList; imageButton.Padding = Padding; imageButton.Size = Size; imageButton.Text = Text; imageButton.TextAlign = TextAlign; imageButton.TextImageRelation = TextImageRelation; imageButton.UseCompatibleTextRendering = UseCompatibleTextRendering; imageButton.UseMnemonic = UseMnemonic; InvokePaint(imageButton, pevent); } class TransparentControl : Control { protected override void OnPaintBackground(PaintEventArgs pevent) { } protected override void OnPaint(PaintEventArgs e) { } } private static GraphicsPath CreateRoundRectangle(Rectangle rectangle, int radius) { radius += 10; GraphicsPath path = new GraphicsPath(); int l = rectangle.Left; int t = rectangle.Top; int w = rectangle.Width; int h = rectangle.Height; int d = radius << 1; path.AddArc(l, t, d, d, 180, 90); // topleft path.AddLine(l + radius, t, l + w - radius, t); // top path.AddArc(l + w - d, t, d, d, 270, 90); // topright path.AddLine(l + w, t + radius, l + w, t + h - radius); // right path.AddArc(l + w - d, t + h - d, d, d, 0, 90); // bottomright path.AddLine(l + w - radius, t + h, l + radius, t + h); // bottom path.AddArc(l, t + h - d, d, d, 90, 90); // bottomleft path.AddLine(l, t + h - radius, l, t + radius); // left path.CloseFigure(); return path; } private static GraphicsPath CreateTopRoundRectangle(Rectangle rectangle, int radius) { radius += 10; GraphicsPath path = new GraphicsPath(); int l = rectangle.Left; int t = rectangle.Top; int w = rectangle.Width; int h = rectangle.Height; int d = radius << 1; path.AddArc(l, t, d, d, 180, 90); // topleft path.AddLine(l + radius, t, l + w - radius, t); // top path.AddArc(l + w - d, t, d, d, 270, 90); // topright path.AddLine(l + w, t + radius, l + w, t + h); // right path.AddLine(l + w, t + h, l, t + h); // bottom path.AddLine(l, t + h, l, t + radius); // left path.CloseFigure(); return path; } private static GraphicsPath CreateBottomRadialPath(Rectangle rectangle) { GraphicsPath path = new GraphicsPath(); RectangleF rect = rectangle; rect.X -= rect.Width * .35f; rect.Y -= rect.Height * .15f; rect.Width *= 1.7f; rect.Height *= 2.3f; path.AddEllipse(rect); path.CloseFigure(); return path; } #endregion #region " Unused Properties & Events " /// This property is not relevant for this class. /// This property is not relevant for this class. [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)] public new FlatButtonAppearance FlatAppearance { get { return base.FlatAppearance; } } /// This property is not relevant for this class. /// This property is not relevant for this class. [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)] public new FlatStyle FlatStyle { get { return base.FlatStyle; } set { base.FlatStyle = value; } } /// This property is not relevant for this class. /// This property is not relevant for this class. [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)] public new bool UseVisualStyleBackColor { get { return base.UseVisualStyleBackColor; } set { base.UseVisualStyleBackColor = value; } } #endregion #region " Animation Support " private List frames; private const int FRAME_DISABLED = 0; private const int FRAME_PRESSED = 1; private const int FRAME_NORMAL = 2; private const int FRAME_ANIMATED = 3; private bool HasAnimationFrames { get { return frames != null && frames.Count > FRAME_ANIMATED; } } private void CreateFrames() { CreateFrames(false); } private void CreateFrames(bool withAnimationFrames) { DestroyFrames(); if (!IsHandleCreated) { return; } if (frames == null) { frames = new List(); } frames.Add(CreateBackgroundFrame(false, false, false, false, 0)); frames.Add(CreateBackgroundFrame(true, true, false, true, 0)); frames.Add(CreateBackgroundFrame(false, false, false, true, 0)); if (!withAnimationFrames) { return; } for (int i = 0; i < framesCount; i++) { frames.Add(CreateBackgroundFrame(false, true, true, true, (float)i / (framesCount - 1F))); } } private void DestroyFrames() { if (frames != null) { while (frames.Count > 0) { frames[frames.Count - 1].Dispose(); frames.RemoveAt(frames.Count - 1); } } } private const int animationLength = 300; private const int framesCount = 10; private int currentFrame; private int direction; private bool isAnimating { get { return direction != 0; } } private void FadeIn() { direction = 1; timer.Enabled = true; } private void FadeOut() { direction = -1; timer.Enabled = true; } private void timer_Tick(object sender, EventArgs e) { if (!timer.Enabled) { return; } Refresh(); currentFrame += direction; if (currentFrame == -1) { currentFrame = 0; timer.Enabled = false; direction = 0; return; } if (currentFrame == framesCount) { currentFrame = framesCount - 1; timer.Enabled = false; direction = 0; } } #endregion } }