using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; using Vanara.Interop.DesktopWindowManager; namespace AeroWizard { /// /// A button that displays an image and no text. /// [ToolboxItem(true), ToolboxBitmap(typeof(ThemedImageButton), "ThemedImageButton.bmp")] public class ThemedImageButton : ButtonBase { private const string defaultText = ""; private const string defaultToolTip = "Returns to a previous page"; private ToolTip toolTip; private VisualStyleRenderer rnd = null; /// /// Initializes a new instance of the class. /// public ThemedImageButton() { SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true); ButtonState = PushButtonState.Normal; toolTip = new ToolTip(); toolTip.SetToolTip(this, defaultToolTip); StyleClass = "BUTTON"; StylePart = 1; Text = defaultText; } /// /// Gets or sets the background color of the control. /// /// A value representing the background color. public override Color BackColor { get { return OnGlass ? Color.Transparent : base.BackColor; } set { base.BackColor = value; } } /// /// Gets or sets the image that is displayed on a button control. /// /// The displayed on the button control. The default value is null. public new Image Image { get { return base.Image; } set { if (value != null) { InitializeImageList(value.Size); ImageList.Images.Add(value); } else ImageList = null; base.Image = value; } } /// /// Gets or sets the style class. /// /// The style class. [DefaultValue("BUTTON"), Category("Appearance")] public string StyleClass { get; set; } /// /// Gets or sets the style part. /// /// The style part. [DefaultValue(1), Category("Appearance")] public int StylePart { get; set; } /// /// Gets or sets the text associated with this control. /// /// /// The text associated with this control. /// [DefaultValue(defaultText), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)] public override string Text { get { return base.Text; } set { base.Text = value; } } /// /// Gets or sets the tool tip text. /// /// The tool tip text. [DefaultValue(defaultToolTip), Category("Appearance")] public string ToolTipText { get { return toolTip.GetToolTip(this); } set { toolTip.SetToolTip(this, value); } } /// /// Gets or sets the state of the button. /// /// The state of the button. protected PushButtonState ButtonState { get; set; } /// /// Gets a value indicating whether on glass. /// /// true if on glass; otherwise, false. private bool OnGlass => !this.IsDesignMode() && DesktopWindowManager.CompositionEnabled; /// /// Retrieves the default size for the control. /// /// /// /// The default of the control. /// protected override Size DefaultSize => new Size(30, 30); /// /// Retrieves the size of a rectangular area into which a control can be fitted. /// /// The custom-sized area for a control. /// /// An ordered pair of type representing the width and height of a rectangle. /// public override Size GetPreferredSize(Size proposedSize) => DefaultSize; /// /// For button user use to simulate a click operate. /// public void PerformClicked() { base.OnClick(EventArgs.Empty); } /// /// Sets the image list images using an image strip. /// /// The image strip. /// The orientation of the strip. public void SetImageListImageStrip(Image imageStrip, Orientation orientation) { if (imageStrip == null) ImageList = null; else { Size imageSize = orientation == Orientation.Vertical ? new Size(imageStrip.Width, imageStrip.Height / 4) : new Size(imageStrip.Width / 4, imageStrip.Height); InitializeImageList(imageSize); using (Bitmap bmp = new Bitmap(imageStrip)) { for (Rectangle r = new Rectangle(Point.Empty, imageSize); r.Y < imageStrip.Height; r.Y += imageSize.Height) ImageList.Images.Add(bmp.Clone(r, bmp.PixelFormat)); } } } /// /// Process Enabled property changed /// /// The instance containing the event data. protected override void OnEnabledChanged(EventArgs e) { ButtonState = Enabled ? PushButtonState.Normal : PushButtonState.Disabled; Invalidate(); base.OnEnabledChanged(e); } /// /// Raises the event. /// /// The instance containing the event data. protected override void OnGotFocus(EventArgs e) { Invalidate(); base.OnGotFocus(e); } /// /// Raises the event. /// /// The instance containing the event data. protected override void OnLostFocus(EventArgs e) { Invalidate(); base.OnLostFocus(e); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnMouseDown(MouseEventArgs e) { if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return; ButtonState = PushButtonState.Pressed; Invalidate(); base.OnMouseDown(e); } /// /// Raises the event. /// /// An that contains the event data. protected override void OnMouseEnter(EventArgs e) { ButtonState = PushButtonState.Hot; Invalidate(); base.OnMouseEnter(e); } /// /// Raises the event. /// /// An that contains the event data. protected override void OnMouseLeave(EventArgs e) { ButtonState = Enabled ? PushButtonState.Normal : PushButtonState.Disabled; Invalidate(); base.OnMouseLeave(e); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnMouseUp(MouseEventArgs e) { if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return; ButtonState = Enabled ? PushButtonState.Hot : PushButtonState.Disabled; Invalidate(); base.OnMouseUp(e); } /// /// Raises the event. /// /// A that contains the event data. protected override void OnPaint(PaintEventArgs e) { if (Visible) { Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.HighQuality; g.CompositingQuality = CompositingQuality.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; PaintButton(e.Graphics, e.ClipRectangle); } } /// /// Paints the background of the control. /// /// A that contains information about the control to paint. protected override void OnPaintBackground(PaintEventArgs pevent) { base.OnPaintBackground(pevent); } /// /// Primary function for painting the button. This method should be overridden instead of OnPaint. /// /// The graphics. /// The bounds. protected virtual void PaintButton(Graphics graphics, Rectangle bounds) { System.Diagnostics.Debug.WriteLine($"PaintButton: desMode:{this.IsDesignMode()};vsEnabled:{Application.RenderWithVisualStyles};vsOnOS:{VisualStyleInformation.IsSupportedByOS};btnState:{ButtonState};enabled:{Enabled};imgCt:{(ImageList != null ? ImageList.Images.Count : 0)}"); if (InitializeRenderer()) { if (OnGlass) { rnd.DrawGlassBackground(graphics, bounds, bounds); } else { rnd.DrawParentBackground(graphics, bounds, this); rnd.DrawBackground(graphics, bounds); } } else { if (ImageList != null && ImageList.Images.Count > 0) { int idx = (int)ButtonState - 1; if (ImageList.Images.Count == 1) idx = 0; else if (ImageList.Images.Count == 2) idx = ButtonState == PushButtonState.Disabled ? 1 : 0; else if (ImageList.Images.Count == 3) idx = ButtonState == PushButtonState.Normal ? 0 : idx - 1; bool forceDisabled = !Enabled && ImageList.Images.Count == 1; if (OnGlass) { VisualStyleRendererExtension.DrawGlassImage(null, graphics, bounds, ImageList.Images[idx], forceDisabled); } else { if (!Application.RenderWithVisualStyles && VisualStyleInformation.IsSupportedByOS) { System.Drawing.Drawing2D.GraphicsContainer g = graphics.BeginContainer(); Rectangle translateRect = bounds; graphics.TranslateTransform(-bounds.Left, -bounds.Top); PaintEventArgs pe = new PaintEventArgs(graphics, translateRect); InvokePaintBackground(Parent, pe); InvokePaint(Parent, pe); graphics.ResetTransform(); graphics.EndContainer(g); } else graphics.Clear(Parent.BackColor); if (forceDisabled) ControlPaint.DrawImageDisabled(graphics, ImageList.Images[idx], 0, 0, Color.Transparent); else { //base.ImageList.Draw(graphics, bounds.X, bounds.Y, bounds.Width, bounds.Height, idx); //VisualStyleRendererExtender.DrawGlassImage(null, graphics, bounds, base.ImageList.Images[idx], forceDisabled); // Not 7 graphics.DrawImage(ImageList.Images[idx], bounds, bounds, GraphicsUnit.Pixel); // Works on XP, not 7, with Parent.BackColor } } } /*else if (this.ImageList != null && this.ImageList.Images.Count > 1) { int idx = (int)ButtonState - 1; if (this.ImageList.Images.Count == 2) idx = ButtonState == PushButtonState.Disabled ? 1 : 0; if (this.ImageList.Images.Count == 3) idx = ButtonState == PushButtonState.Normal ? 0 : idx - 1; if (rnd != null && !this.IsDesignMode() && DesktopWindowManager.IsCompositionEnabled()) rnd.DrawGlassIcon(graphics, bounds, this.ImageList, idx); else this.ImageList.Draw(graphics, bounds.X, bounds.Y, bounds.Width, bounds.Height, idx); }*/ // No image so draw standard button else { ButtonRenderer.DrawParentBackground(graphics, bounds, this); ButtonRenderer.DrawButton(graphics, bounds, ButtonState); } } if (Focused) ControlPaint.DrawFocusRectangle(graphics, bounds); } private void InitializeImageList(Size imageSize) { ImageList = new ImageList() { ImageSize = imageSize, ColorDepth = ColorDepth.Depth32Bit, TransparentColor = Color.Transparent }; } private bool InitializeRenderer() { if (Application.RenderWithVisualStyles) { try { if (rnd == null) rnd = new VisualStyleRenderer(StyleClass, StylePart, (int)ButtonState); else rnd.SetParameters(StyleClass, StylePart, (int)ButtonState); return true; } catch { } } return false; } } }