![](/wp-content/uploads/2024/01/Custom-Form.png)
While the default .NET forms are functional, they often lack the contemporary aesthetics and dynamic features of modern applications. This tutorial will guide you through transforming a basic .NET form into a custom, interactive interface with a sleek, Windows 10-style glass look.
Creating the Form
Set Up the Basic Form
To start, inherit a basic Windows form and customize it to your requirements. Begin by adjusting the form’s appearance, removing the default border, and setting an opaque background.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Basic form setup
this.FormBorderStyle = FormBorderStyle.None;
this.BackColor = Color.Black; // Semi-transparent black background
this.Opacity = 0.8; // Adjust for desired transparency
this.StartPosition = FormStartPosition.CenterScreen;
this.Size = new Size(450, 450);
this.Padding = new Padding(1); // White border
}
Note that modifying the form from code may not update the design page of your integrated development environment (IDE), but it will still function correctly for adding elements.
Create a new border.
Since the default border doesn’t align with the desired look, override the OnPaint
method for the form to draw a custom border using the Graphics object.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (Pen pen = new Pen(Color.White, 1))
{
e.Graphics.DrawRectangle(pen, 0, 0, this.Width - 1, this.Height - 1); // White border
}
}
}
Adding a Custom Top Bar
Design the Top Bar
With the old border removed, you’ll need to recreate the top bar and its associated functionality. Create a simple panel with a white border, matching the form’s appearance. Place a button labelled ‘X
‘ on top to serve as the close button. Add a method to adjust its background to red when the mouse hovers over it. Subscribe the close form method to the button click.
Add a variable to the Form1
class for the tile bar.
private readonly Panel titleBar;
Add the panel constructer to the Form1
initializer.
// Custom title bar
titleBar = new Panel
{
Dock = DockStyle.Top,
Height = 30,
BackColor = Color.Black,
BorderStyle = BorderStyle.Fixed3D
};
this.Controls.Add(titleBar);
// Close button
Button closeButton = new Button
{
Text = "X",
ForeColor = Color.White,
BackColor = Color.Transparent,
FlatStyle = FlatStyle.Flat,
FlatAppearance = { BorderSize = 1,
BorderColor = Color.White},
Location = new Point(this.Width - 30, 0),
Size = new Size(30, 30),
};
// Event handler for mouse entering the button area
closeButton.MouseEnter += (sender, e) =>
{
closeButton.BackColor = Color.Crimson; // Change to red when mouse is over
};
// Event handler for mouse leaving the button area
closeButton.MouseLeave += (sender, e) =>
{
closeButton.BackColor = Color.Transparent; // Change back to transparent when mouse leaves
};
closeButton.Click += (s, e) => { this.Close(); };
titleBar.Controls.Add(closeButton);
// Ensuring the close button is repositioned correctly on resize
this.Resize += (s, e) => { closeButton.Location = new Point(this.Width - 30, -2); };
Add Drag Functionality
To enable the form to be draggable, subscribe the panel to mouse events for clicking and dragging. Implement the necessary functionality within these events.
Add methods for the event handlers to the Form1
class
private bool dragging = false;
private Point dragCursorPoint;
private Point dragFormPoint;
private void TitleBar_MouseDown(object sender, MouseEventArgs e)
{
dragging = true;
dragCursorPoint = Cursor.Position;
dragFormPoint = this.Location;
}
private void TitleBar_MouseMove(object sender, MouseEventArgs e)
{
if (dragging)
{
Point currentScreenPos = Cursor.Position;
Point adjustedDelta = new Point(
currentScreenPos.X - dragCursorPoint.X,
currentScreenPos.Y - dragCursorPoint.Y);
this.Location = new Point(
dragFormPoint.X + adjustedDelta.X,
dragFormPoint.Y + adjustedDelta.Y);
}
}
private void TitleBar_MouseUp(object sender, MouseEventArgs e)
{
dragging = false;
}
Add the event handlers to the form initializer.
titleBar.MouseDown += new MouseEventHandler(TitleBar_MouseDown);
titleBar.MouseMove += new MouseEventHandler(TitleBar_MouseMove);
titleBar.MouseUp += new MouseEventHandler(TitleBar_MouseUp);
Creating Dynamic Borders for Labels
Designing the Label Borders
Similar to customizing the form, you’ll need to create a custom variant of a label to add to the form. Override the OnPaint
method of the label and assign a custom method to draw the border.
public class GradientBorderLabel : Label
{
public Point? CurrentMousePosition { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (CurrentMousePosition.HasValue)
{
DrawGradientBorder(e.Graphics, CurrentMousePosition.Value);
}
}
private void DrawGradientBorder(Graphics graphics, Point point)
{
var rect = this.ClientRectangle;
rect.Inflate(0, 0); // Adjust to fit inside padding
using (var path = new GraphicsPath())
{
path.AddRectangle(rect);
using (var brush = new PathGradientBrush(path))
{
brush.CenterPoint = point;
brush.CenterColor = Color.FromArgb(255, 255, 255); // White center
brush.SurroundColors = new Color[] { Color.Transparent }; // Transparent edges
graphics.DrawPath(new Pen(brush, 2), path); // Draw gradient border
}
}
}
}
Add Mouse Interaction
To make label borders update based on mouse position, create a method that listens to system messages, filtering out mouse move messages. Extract the coordinates from these messages and check the relative position of the mouse compared to the labels. When the mouse is within range of a label, send the mouse position to the label to update its border.
Create a new class to handle the message filtering.
public class MouseMessageFilter : IMessageFilter
{
public event MouseEventHandler MouseMoved;
public bool PreFilterMessage(ref Message m)
{
// WM_MOUSEMOVE = 0x0200
if (m.Msg == 0x0200)
{
Point screenPosition = Cursor.Position;
MouseMoved?.Invoke(null, new MouseEventArgs(MouseButtons.None, 0, screenPosition.X, screenPosition.Y, 0));
}
return false; // Allow message to continue to the next filter or control
}
}
Add position calculation to the Form1
class.
private readonly MouseMessageFilter _mouseMessageFilter = new MouseMessageFilter();
private void GlobalMouseMoved(object sender, MouseEventArgs e)
{
foreach (Control control in this.Controls)
{
if (control is GradientBorderLabel label)
{
Point relativePoint = label.PointToClient(new Point(e.X, e.Y));
if (IsMouseNearLabel(relativePoint, label.Size))
{
label.CurrentMousePosition = relativePoint;
}
else
{
label.CurrentMousePosition = null;
}
label.Invalidate();
}
}
}
private bool IsMouseNearLabel(Point mousePosition, Size labelSize)
{
// Define proximity area (e.g., 20 pixels around the label)
int proximityArea = 400;
return mousePosition.X >= -proximityArea &&
mousePosition.Y >= -proximityArea &&
mousePosition.X <= labelSize.Width + proximityArea &&
mousePosition.Y <= labelSize.Height + proximityArea;
}
And add a subscriber to the form initialization.
Application.AddMessageFilter(_mouseMessageFilter);
_mouseMessageFilter.MouseMoved += GlobalMouseMoved;
Add labels to the form.
Now that you have custom labels, you can add them to the form just like regular labels.
GradientBorderLabel label1 = new GradientBorderLabel
{
Text = "Label 1",
Location = new Point(50, 100),
Size = new Size(100, 30),
BackColor = Color.Black,
ForeColor = Color.White
};
this.Controls.Add(label1);
GradientBorderLabel label2 = new GradientBorderLabel
{
Text = "Label 2",
Location = new Point(50, 140),
Size = new Size(100, 30),
BackColor = Color.Black,
ForeColor = Color.White,
};
this.Controls.Add(label2);
The complete Code
public partial class Form1 : Form
{
private readonly Panel titleBar;
private readonly MouseMessageFilter _mouseMessageFilter = new MouseMessageFilter();
public Form1()
{
InitializeComponent();
Application.AddMessageFilter(_mouseMessageFilter);
_mouseMessageFilter.MouseMoved += GlobalMouseMoved;
// Basic form setup
this.FormBorderStyle = FormBorderStyle.None;
this.BackColor = Color.Black; // Semi-transparent black background
this.Opacity = 0.8; // Adjust for desired transparency
this.StartPosition = FormStartPosition.CenterScreen;
this.Size = new Size(450, 450);
this.Padding = new Padding(1); // White border
// Custom title bar
titleBar = new Panel
{
Dock = DockStyle.Top,
Height = 30,
BackColor = Color.Black,
BorderStyle = BorderStyle.Fixed3D
};
titleBar.MouseDown += new MouseEventHandler(TitleBar_MouseDown);
titleBar.MouseMove += new MouseEventHandler(TitleBar_MouseMove);
titleBar.MouseUp += new MouseEventHandler(TitleBar_MouseUp);
this.Controls.Add(titleBar);
// Close button
Button closeButton = new Button
{
Text = "X",
ForeColor = Color.White,
BackColor = Color.Transparent,
FlatStyle = FlatStyle.Flat,
FlatAppearance = { BorderSize = 1,
BorderColor = Color.White},
Location = new Point(this.Width - 30, 0),
Size = new Size(30, 30),
};
closeButton.Click += (s, e) => { this.Close(); };
titleBar.Controls.Add(closeButton);
// Ensuring the close button is repositioned correctly on resize
this.Resize += (s, e) => { closeButton.Location = new Point(this.Width - 30, -2); };
GradientBorderLabel label1 = new GradientBorderLabel
{
Text = "Label 1",
Location = new Point(50, 100),
Size = new Size(100, 30),
BackColor = Color.Black,
ForeColor = Color.White
};
this.Controls.Add(label1);
GradientBorderLabel label2 = new GradientBorderLabel
{
Text = "Label 1",
Location = new Point(50, 140),
Size = new Size(100, 30),
BackColor = Color.Black,
ForeColor = Color.White,
};
this.Controls.Add(label2);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (Pen pen = new Pen(Color.White, 1))
{
e.Graphics.DrawRectangle(pen, 0, 0, this.Width - 1, this.Height - 1); // White border
}
}
private bool dragging = false;
private Point dragCursorPoint;
private Point dragFormPoint;
private void TitleBar_MouseDown(object sender, MouseEventArgs e)
{
dragging = true;
dragCursorPoint = Cursor.Position;
dragFormPoint = this.Location;
}
private void TitleBar_MouseMove(object sender, MouseEventArgs e)
{
if (dragging)
{
Point currentScreenPos = Cursor.Position;
Point adjustedDelta = new Point(
currentScreenPos.X - dragCursorPoint.X,
currentScreenPos.Y - dragCursorPoint.Y);
this.Location = new Point(
dragFormPoint.X + adjustedDelta.X,
dragFormPoint.Y + adjustedDelta.Y);
}
}
private void TitleBar_MouseUp(object sender, MouseEventArgs e)
{
dragging = false;
}
private void GlobalMouseMoved(object sender, MouseEventArgs e)
{
foreach (Control control in this.Controls)
{
if (control is GradientBorderLabel label)
{
Point relativePoint = label.PointToClient(new Point(e.X, e.Y));
if (IsMouseNearLabel(relativePoint, label.Size))
{
label.CurrentMousePosition = relativePoint;
}
else
{
label.CurrentMousePosition = null;
}
label.Invalidate();
}
}
}
private bool IsMouseNearLabel(Point mousePosition, Size labelSize)
{
// Define proximity area (e.g., 20 pixels around the label)
int proximityArea = 400;
return mousePosition.X >= -proximityArea &&
mousePosition.Y >= -proximityArea &&
mousePosition.X <= labelSize.Width + proximityArea &&
mousePosition.Y <= labelSize.Height + proximityArea;
}
}
public class MouseMessageFilter : IMessageFilter
{
public event MouseEventHandler MouseMoved;
public bool PreFilterMessage(ref Message m)
{
// WM_MOUSEMOVE = 0x0200
if (m.Msg == 0x0200)
{
Point screenPosition = Cursor.Position;
MouseMoved?.Invoke(null, new MouseEventArgs(MouseButtons.None, 0, screenPosition.X, screenPosition.Y, 0));
}
return false; // Allow message to continue to the next filter or control
}
}
public class GradientBorderLabel : Label
{
public Point? CurrentMousePosition { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (CurrentMousePosition.HasValue)
{
DrawGradientBorder(e.Graphics, CurrentMousePosition.Value);
}
}
private void DrawGradientBorder(Graphics graphics, Point point)
{
var rect = this.ClientRectangle;
rect.Inflate(0, 0); // Adjust to fit inside padding
using (var path = new GraphicsPath())
{
path.AddRectangle(rect);
using (var brush = new PathGradientBrush(path))
{
brush.CenterPoint = point;
brush.CenterColor = Color.FromArgb(255, 255, 255); // White center
brush.SurroundColors = new Color[] { Color.Transparent }; // Transparent edges
graphics.DrawPath(new Pen(brush, 2), path); // Draw gradient border
}
}
}
}
Leave a Reply