Karedia Noorsil
Karedia Noorsil

Reputation: 470

how to design a custom close, minimize and maximize button in windows form application?

I am creating a windows form application project in which I want a custom border and three buttons(close, minimize and maximize) of my own design. I have no idea how to do it and I'm not even sure if it is possible. But if its possible please let me know the solution. Thanks

Upvotes: 9

Views: 45938

Answers (5)

FantaOrangeFanBoy
FantaOrangeFanBoy

Reputation: 51

I know it is old but hopefully it helps someone...

Rather than using 'maximised', use 'working area' otherwise it covers the taskbar.

have a global bool: private static bool trip = false;

Then in your function:

        if (trip == false)
        {
            Left = Top = 0;
            Width = Screen.PrimaryScreen.WorkingArea.Width;
            Height = Screen.PrimaryScreen.WorkingArea.Height;
            trip = true;
        }
        else if (trip == true)
        {
            Width = 1535; // my original form size
            Height = 937; // my original form size
            this.Left = leftPOS; // POS are filled on form load for current positions
            this.Top = topPOS;
            trip = false;
        }

without the trip bool, I was unable to return the form to the normal size after pressing the maximise button again.

Upvotes: 0

Orestis
Orestis

Reputation: 11

A small detail not covered by @Pierre_Luc. If you add any Controls on that Panel, e.g. a Title or an Icon, the Form won't be draggable when clicked on these Controls. To achieve this, I found it convenient to add the same event handler to all the Controls (except from the Minimize, Maximize and Close Buttons) in the Load Event of the Form.

private void Form1_Load(object sender, EventArgs e)
    {
        foreach (Control Control in this.HeaderPanel.Controls)
        {
            if (!(Control is Button)) //Change here depending on the Library you use for your contols
            {
                Control.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OnMouseDown);
            }
        }
    }

Morevoer, here is a complete version of WndProc that provides resizing in all directions (Left, Right, Bottom).

protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x84)
        {
            const int resizeArea = 10;
            Point cursorPosition = PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16));
            if (cursorPosition.X >= ClientSize.Width - resizeArea && cursorPosition.Y >= ClientSize.Height - resizeArea)
            {
                m.Result = (IntPtr)17; //HTBOTTOMRIGHT
                return;
            }
            else if (cursorPosition.X <= resizeArea && cursorPosition.Y >= ClientSize.Height - resizeArea)
            {
                m.Result = (IntPtr)16; //HTBOTTOMLEFT
                return;
            }
            else if (cursorPosition.X <= resizeArea)
            {
                m.Result = (IntPtr)10; //HTLEFT
                return;
            }
            else if (cursorPosition.X >= ClientSize.Width - resizeArea)
            {
                m.Result = (IntPtr)11; //HTRIGHT
                return;
            }
            else if (cursorPosition.Y >= ClientSize.Height - resizeArea)
            {
                m.Result = (IntPtr)15; //HTBOTTOM
                return;
            }
        }

        base.WndProc(ref m);
    }

Upvotes: 1

Serge Kishiko
Serge Kishiko

Reputation: 486

Just to complete the useful solution of @Pierre-Luc. When the window is maximized, how to resize it to its normal position if we click again to the maximize button. Here is the code:

private static bool MAXIMIZED = false;
private void maximizeButton_Click(object sender, System.EventArgs e)
{
    if(MAXIMIZED)
    {
        WindowState = FormWindowState.Normal;
        MAXIMIZED = false;
    }
    else
    {
        WindowState = FormWindowState.Maximized;
        MAXIMIZED = true;
    }
}

EDIT: As suggested by @LarsTech in the comment

private void maximizeButton_Click(object sender, System.EventArgs e)
{
    if (this.WindowState != FormWindowState.Maximized)
        this.WindowState = FormWindowState.Maximized;
    else
        this.WindowState = FormWindowState.Normal;
}

Upvotes: 5

Pierre-Luc Pineault
Pierre-Luc Pineault

Reputation: 9201

Yes, it's possible without additional libraries.

First, hide the window's original border.

public Form1()
{
    InitializeComponent();

    FormBorderStyle = FormBorderStyle.None;
}

Next, create a panel, or whatever you want really, with your three buttons (I know it's ugly, for demo purposes):

enter image description here

Then, assign the correct action to each of them, using the WindowState:

private void minimizeButton_Click(object sender, System.EventArgs e)
{
    WindowState = FormWindowState.Minimized;
}

private void maximizeButton_Click(object sender, System.EventArgs e)
{
    WindowState = FormWindowState.Maximized;
}

private void closeButton_Click(object sender, System.EventArgs e)
{
    Close();
}

Finally, make the form draggable with our panel. Add those at the class level:

public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HTCAPTION = 0x2;
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

and plug them in a MouseDown event of the panel:

private void OnMouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        ReleaseCapture();
        SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
    }
}

And now you have a draggable form, with your own bar at the top.

If you want it to be resizable, as @PhilWright mentionned, you can trap the WM_NCHITTEST message from WndProc and return HTBOTTOMRIGHT to trigger the resizing :

protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x84)
    { 
        const int resizeArea = 10;
        Point cursorPosition = PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16));
        if (cursorPosition.X >= ClientSize.Width - resizeArea && cursorPosition.Y >= ClientSize.Height - resizeArea )
        {
            m.Result = (IntPtr)17;
            return;
        }
    }

    base.WndProc(ref m);
}

As @BenVoigt mentionned, you can use the Dock and Anchor properties on the buttons/panel so they can resize properly. If you don't, they will not follow the form on resize.

Upvotes: 33

Phil Wright
Phil Wright

Reputation: 22926

It is certainly possible but not for the beginner. Major component vendors such as Infragistics, DevExpress, ComponentOne, SyncFusion and others have libraries that provide the ability to customize the appearance of the Form.

Upvotes: -1

Related Questions