1

I want to create an borderless WinForm which has a custom header with the Default System Icons for:

  • Minimization
  • Maximization
  • Closing

Is there any Way i can achieve this in C# or VB?

Error404
  • 719
  • 9
  • 30
  • You could use buttons with images for that... – Zohar Peled Aug 04 '16 at 07:54
  • @ZoharPeled But I want to display the Default Icons for those options which are not always the same – Error404 Aug 04 '16 at 07:55
  • They are not icons, they are painted. The way they look changes with every Windows version, the window chrome is the basic way Microsoft makes their releases look "new and appealing". Starting with Win8, an app can no longer draw them to match the OS theme and always gets the legacy visual style renderer. Pretty visible in Visual Studio when you design a Winforms form, note how the frame style is wrong and looks like the Win7 version. Given that you can't get it right anyway, best to just [do it yourself](http://stackoverflow.com/a/23139022/17034). – Hans Passant Aug 04 '16 at 08:29
  • The actual images can be (at least in Win7) found in `Aero.msstyles` (located somewhere in `%SystemRoot%\Resources` i think), the only question would be how you're going to read that from your application. – Visual Vincent Aug 04 '16 at 08:39

3 Answers3

3

For everyone how wants a fully customizable button in the windows 10 aero style.

Here it is:

First, a base class which fixes the error, that a button which is focused gets an outline when the form loses focus:

using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsControls {
    /// <summary>
    /// Modified button which has no focus rectangles when the form which contains this button loses fucus while the button was focused.
    /// </summary>
    [ToolboxItem(typeof(NoFocusCueBotton))]
    public class NoFocusCueBotton : Button {
        protected override bool ShowFocusCues => false;

        /// <summary>
        /// Creates a new instance of a <see cref="NoFocusCueBotton"/>
        /// </summary>
        public NoFocusCueBotton() { }

        public override void NotifyDefault(bool value) {
            base.NotifyDefault(false);
        }
    }
}

Next the actual button:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsControls {
    /// <summary>
    /// Button which represents the default close, minimize or maximize buttons of the windows 10 aero theme.
    /// </summary>
    [ToolboxItem(true)]
    public class WindowsDefaultTitleBarButton : NoFocusCueBotton {
        /// <summary>
        /// Represents the 3 possible types of the windows border buttons.
        /// </summary>
        public enum Type {
            Close,
            Maximize,
            Minimize
        }

        private Pen activeIconColorPen;
        private Brush activeIconColorBrush;
        private Brush activeColorBrush;

        /// <summary>
        /// The type which defines the buttons behaviour.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)]
        [DefaultValue(Type.Close)]
        [Category("Appearance")]
        [Description("The type which defines the buttons behaviour.")]
        public Type ButtonType { get; set; }

        /// <summary>
        /// The background color of the button when the mouse is inside the buttons bounds.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)]
        [DefaultValue(null)]
        [Category("Appearance")]
        [Description("The background color of the button when the mouse is inside the buttons bounds.")]
        public Color HoverColor { get; set; }

        /// <summary>
        /// The background color of the button when the button is clicked.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)]
        [DefaultValue(null)]
        [Category("Appearance")]
        [Description("The background color of the button when the button is clicked.")]
        public Color ClickColor { get; set; }

        /// <summary>
        /// The default color of the icon.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)]
        [DefaultValue(null)]
        [Category("Appearance")]
        [Description("The default color of the icon.")]
        public Color IconColor { get; set; }

        /// <summary>
        /// The color of the icon when the mouse is inside the buttons bounds.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)]
        [DefaultValue(null)]
        [Category("Appearance")]
        [Description("The color of the icon when the mouse is inside the buttons bounds.")]
        public Color HoverIconColor { get; set; }

        /// <summary>
        /// The color of the icon when the button is clicked.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Browsable(true)]
        [DefaultValue(null)]
        [Category("Appearance")]
        [Description("The color of the icon when the button is clicked.")]
        public Color ClickIconColor { get; set; }

        /// <summary>
        /// Property which returns the active background color of the button depending on if the button is clicked or hovered.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Browsable(false)]
        public virtual Color ActiveColor {
            get {
                if (this.Clicked)
                    return this.ClickColor;

                if (this.Hovered)
                    return this.HoverColor;

                return BackColor;
            }
        }

        /// <summary>
        /// Property which returns the active color of the buttons icon depending on if the button is clicked or hovered.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Browsable(false)]
        public virtual Color ActiveIconColor {
            get {
                if (this.Clicked)
                    return this.ClickIconColor;

                if (this.Hovered)
                    return this.HoverIconColor;

                return IconColor;
            }
        }

        /// <summary>
        /// Property which indicates if the mouse is currently inside the bounds of the button.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Browsable(false)]
        [DefaultValue(false)]
        public bool Hovered { get; set; }

        /// <summary>
        /// Property which indicates if the left mouse button was pressed down inside the buttons bounds. Can be true before the click event is triggered.
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Browsable(false)]
        [DefaultValue(false)]
        public bool Clicked { get; set; }

        public WindowsDefaultTitleBarButton() { }

        protected override void OnMouseEnter(EventArgs e) {
            base.OnMouseEnter(e);
            Hovered = true;
        }

        protected override void OnMouseLeave(EventArgs e) {
            base.OnMouseLeave(e);
            Hovered = false;
        }

        protected override void OnMouseDown(MouseEventArgs mevent) {
            base.OnMouseDown(mevent);
            Clicked = true;
        }

        protected override void OnMouseUp(MouseEventArgs mevent) {
            base.OnMouseUp(mevent);
            Clicked = false;
        }

        protected override void OnClick(EventArgs e) {
            if (ButtonType == Type.Close)
                this.FindForm()?.Close();
            else if (ButtonType == Type.Maximize)
                this.FindForm().WindowState = this.FindForm().WindowState == FormWindowState.Maximized ? FormWindowState.Normal : FormWindowState.Maximized;
            else
                this.FindForm().WindowState = FormWindowState.Minimized;

            base.OnClick(e);
        }

        protected override void OnPaint(PaintEventArgs pevent) {
            System.Diagnostics.Trace.WriteLine(pevent.ClipRectangle.ToString());

            activeColorBrush?.Dispose();
            activeColorBrush = new SolidBrush(ActiveColor);

            pevent.Graphics.FillRectangle(new SolidBrush(ActiveColor), pevent.ClipRectangle);
            pevent.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            activeIconColorBrush?.Dispose();
            activeIconColorPen?.Dispose();

            activeIconColorBrush = new SolidBrush(ActiveIconColor);
            activeIconColorPen = new Pen(activeIconColorBrush, 1.0f);

            if (ButtonType == Type.Close)
                drawCloseIcon(pevent, new Rectangle(0, 0, this.Width, this.Height));
            else if (ButtonType == Type.Maximize)
                drawMaximizeIcon(pevent, new Rectangle(0, 0, this.Width, this.Height));
            else
                drawMinimizeIcon(pevent, new Rectangle(0, 0, this.Width, this.Height));
        }

        protected virtual void drawCloseIcon(PaintEventArgs e, Rectangle drawRect) {
            e.Graphics.DrawLine(
                activeIconColorPen,
                drawRect.X + drawRect.Width / 2 - 5,
                drawRect.Y + drawRect.Height / 2 - 5,
                drawRect.X + drawRect.Width / 2 + 5,
                drawRect.Y + drawRect.Height / 2 + 5);

            e.Graphics.DrawLine(
                activeIconColorPen,
                drawRect.X + drawRect.Width / 2 - 5,
                drawRect.Y + drawRect.Height / 2 + 5,
                drawRect.X + drawRect.Width / 2 + 5,
                drawRect.Y + drawRect.Height / 2 - 5); ;
        }

        protected virtual void drawMaximizeIcon(PaintEventArgs e, Rectangle drawRect) {
            if (this.FindForm().WindowState == FormWindowState.Normal) {
                e.Graphics.DrawRectangle(
                    activeIconColorPen,
                    new Rectangle(
                        drawRect.X + drawRect.Width / 2 - 5,
                        drawRect.Y + drawRect.Height / 2 - 5,
                        10, 10));
            } else if (this.FindForm().WindowState == FormWindowState.Maximized) {
                e.Graphics.DrawRectangle(
                    activeIconColorPen,
                    new Rectangle(
                        drawRect.X + drawRect.Width / 2 - 3,
                        drawRect.Y + drawRect.Height / 2 - 5,
                        8, 8));

                Rectangle rect = new Rectangle(
                    drawRect.X + drawRect.Width / 2 - 5,
                    drawRect.Y + drawRect.Height / 2 - 3,
                    8, 8);

                e.Graphics.FillRectangle(activeIconColorBrush, rect);
                e.Graphics.DrawRectangle(activeIconColorPen, rect);
            }
        }

        protected virtual void drawMinimizeIcon(PaintEventArgs e, Rectangle drawRect) {
            e.Graphics.DrawLine(
                activeIconColorPen,
                drawRect.X + drawRect.Width / 2 - 5,
                drawRect.Y + drawRect.Height / 2,
                drawRect.X + drawRect.Width / 2 + 5,
                drawRect.Y + drawRect.Height / 2);
        }
    }
}

The six colors make the button fully costomizable regarding to the appearance.

Use the WindowsDefaultTitleBarButton.Type ButtonType to chose which behavior and icon the button should have.

Example: Using the color theme of visual studio 2019 project selection window.

enter image description here

Values:

Form:

BackColor: #252526

Close Button:

Size: 46x30

BackColor:  Transparent
HoverColor: #e81123
ClickColor: #f1707a

IconColor:      #f1f1f1
HoverIconColor: #ffffff
ClickIconColor: #ffffff

MinMax Buttons:

Size: 46x30

BackColor:  Transparent
HoverColor: #3f3f40
ClickColor: #007acc

IconColor:      #f1f1f1
HoverIconColor: #ffffff
ClickIconColor: #ffffff
Kaskorian
  • 426
  • 3
  • 18
  • Thank you for this solution, I was able to improve your solution by adding the following features/changes: 1. Added ready-to-use VS 2019 light and dark styles. 2. Added a button with a hamburger menu icon. 3. Set the default button size to 46x30 4. Minor code improvements. My code is written in VB.NET: https://gist.github.com/ahmedosama007/d40ec7c1a742b831b1a69f5ce776db7a – Ahmed Osama Jul 21 '22 at 04:24
  • 1
    @AhmedOsama Nice that it helped you. But you can improve this buttons in a lot of ways. When I coded it I redid a lot of stuff that was already there. 1. Use `FlatAppearance` for BackColors. 2. Instead of drawing the Icons on your own set the text of the button `\uE949 \uE739 \uE923 \uE106` or for your menu `\uE700` using the font `Segoe MDL2 Assets`. Font size 8pt should be okay. Then you only have to set the ForeColor in the mouse events and you dont need `OnPaint` – Kaskorian Jul 28 '22 at 13:29
2

Not sure what your exact goal is, but gernerally, for 'custom'-designs using C# I would prefer WPF (Windows Presentation Foundation) instead of Windows Forms...

I guess it´s possible in Windows Forms too, maybe if you remove the borders as wanted and create 3 Buttons, using the common Windows-symbols as their background? But I´m not sure if it´s working ;)

EDIT :

using a controls 'paint'-event, you should be able to reach your goal:

private void button_Paint(object sender, PaintEventArgs e)
{
    if (VisualStyleRenderer.IsElementDefined(VisualStyleElement.Window.CloseButton.Normal))
    {
        VisualStyleRenderer renderer = new VisualStyleRenderer(VisualStyleElement.Window.CloseButton.Normal);
        Rectangle rectangle1 = new Rectangle(button.Location.X, button.Location.Y, button.Width, button.Height);
        renderer.DrawBackground(e.Graphics, rectangle1);
    }
}

this is checking if you are able to use the styles, and then draw the selected VisualStyleElement (eg. CloseButton, MinButton, etc.) to the button/control´s position.

See VisualStylesElement-CloseButton and Control.Paint-Event for more information.

works fine for me, hope it´s what you´ve been looking for...

BingBingBong
  • 88
  • 10
  • I have to use Windows Forms and I already made the header but i am missing the Buttons which i wanted to display the default system ones – Error404 Aug 04 '16 at 12:29
  • hmm okay, you need the buttons to change like the system ones, if you change the maximized state for example? So the buttons look different, depending on the window´s state? – BingBingBong Aug 04 '16 at 12:45
  • No what I need is to somehow import the default system icons for the Buttons in the Menu Bar – Error404 Aug 04 '16 at 13:19
  • okay, I just can´t understand whatfor... To fit the different versions of Windows-themes on other versions? what´s about Hans Passant´s solution? This seems to be okay for me... – BingBingBong Aug 04 '16 at 13:48
  • I dont want to place them on my custom header, but in the context menu of it, like the default windows one which i cant use for various reasons – Error404 Aug 04 '16 at 14:03
  • Is it also possible to draw the close symbol from the default windows context menu(on header) ? – Error404 Aug 05 '16 at 07:35
  • The default windows context menu is the menu, that shows up if you right-click somewhere eg. desktop... I´ve never seen a close-symbol there? Maybe you mixed that up a bit? – BingBingBong Aug 05 '16 at 08:51
  • I mean that one that is displayed when you right-click on a windowsform default header – Error404 Aug 05 '16 at 09:17
  • Okay, now I´ve got it :) trying to find a solution... I think this is the same issue isin´t it? http://stackoverflow.com/questions/14134718/in-c-sharp-winform-app-how-to-paint-draw-child-form-close-button – BingBingBong Aug 05 '16 at 09:28
  • After doing some research, I´m pretty sure that there is no way to use the context menu symbols in this way... You could try the 'mdi'-buttons eg. MdiCloseButton.Normal ... they still look different, but they get close to your wishes, in my opinion... Or you try to create an exact duplicate of each symbol by drawing it like Hans Passant said earlier... – BingBingBong Aug 05 '16 at 10:46
-2

As per my knowledge you can Use "Anchor property" + "Doc Property" of windows form by placing three buttons with images.

Or here i shown one example that is showing customized theme for windows form with controls.

This sample is in Vb.NET.Save as class in your project,build your project and then controls will be appear in toolbox area.Drag & Drop that control. Enjoy!

Try This T3 Vb.NET Themes Archives

  • 1
    The problem here isn't really how to change the window theme, but he wants the actual Minimize, Maximize and Close images from Windows Aero (or the current theme) _so that he actually has any images to put on the buttons_. – Visual Vincent Aug 04 '16 at 09:20