Reputation: 470
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
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
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
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
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):
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
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