I have been messing around with borderless forms for a few hours and I have been able to get all the functionality that I need from it. The only thing that has been bothering me is when resizing from the top, top-left, or left the form will flicker on the opposite side. The components will as well but I figured out how to deal with that problem. Right now I'm focused on trying to get the flickering to stop while keeping the borderless form completely borderless. I know that the issue stems from the form drawing the moved distance and then redrawing the size (or vice versa) but I cannot get it to stop.
I have tried several different methods of resizing the form from using the PInvoke WndProc method, to just setting the location and size of the form, to trying to lock the form while I am changing the location and size. Nothing seems to get rid of that flickering unless I am using a sizable form. I can hide most of the sizable form but there is still a few pixels of the title bar left. Every method that I have found while searching has yielded the same results.
Here is what I am currently using to inherit from on my Main form:
using System.Drawing;
using System.Windows.Forms;
namespace TestBorderlessModernGUI
{
/// <summary>
/// Inherit from EdgeDrag in the main form
/// </summary>
public class EdgeDrag : Form
{
protected bool isDragging = false;
protected bool canDrag = false;
protected Rectangle lastRectangle = new Rectangle();
public EdgeDrag()
{
}
/// <summary>
/// Call after component Initialization in the Main Form
/// </summary>
protected void InitialiseFormEdge()
{
int resizeWidth = 2;
this.MouseDown += new MouseEventHandler(form_MouseDown);
this.MouseMove += new MouseEventHandler(form_MouseMove);
this.MouseUp += new MouseEventHandler(form_MouseUp);
// bottom
UserControl uc1 = new UserControl()
{
Anchor = (AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right),
Height = resizeWidth,
Width = this.DisplayRectangle.Width - (resizeWidth * 2),
Left = resizeWidth,
Top = this.DisplayRectangle.Height - resizeWidth,
BackColor = Color.Transparent,
Cursor = Cursors.SizeNS
};
uc1.MouseDown += form_MouseDown;
uc1.MouseUp += form_MouseUp;
uc1.MouseMove += delegate (object sender, MouseEventArgs e)
{
if (isDragging)
{
this.Size = new Size(lastRectangle.Width, e.Y - lastRectangle.Y + this.Height);
}
};
uc1.BringToFront();
this.Controls.Add(uc1);
this.Controls.SetChildIndex(uc1, 0);
// right
UserControl uc2 = new UserControl()
{
Anchor = (AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom),
Height = this.DisplayRectangle.Height - (resizeWidth * 2),
Width = resizeWidth,
Left = this.DisplayRectangle.Width - resizeWidth,
Top = resizeWidth,
BackColor = Color.Transparent,
Cursor = Cursors.SizeWE
};
uc2.MouseDown += form_MouseDown;
uc2.MouseUp += form_MouseUp;
uc2.MouseMove += delegate (object sender, MouseEventArgs e)
{
if (isDragging)
{
this.Size = new Size(e.X - lastRectangle.X + this.Width, lastRectangle.Height);
}
};
uc2.BringToFront();
this.Controls.Add(uc2);
this.Controls.SetChildIndex(uc2, 0);
// bottom-right
UserControl uc3 = new UserControl()
{
Anchor = (AnchorStyles.Bottom | AnchorStyles.Right),
Height = resizeWidth,
Width = resizeWidth,
Left = this.DisplayRectangle.Width - resizeWidth,
Top = this.DisplayRectangle.Height - resizeWidth,
BackColor = Color.Transparent,
Cursor = Cursors.SizeNWSE
};
uc3.MouseDown += form_MouseDown;
uc3.MouseUp += form_MouseUp;
uc3.MouseMove += delegate (object sender, MouseEventArgs e)
{
if (isDragging)
{
this.Size = new Size((e.X - lastRectangle.X + this.Width), (e.Y - lastRectangle.Y + this.Height));
}
};
uc3.BringToFront();
this.Controls.Add(uc3);
this.Controls.SetChildIndex(uc3, 0);
// top-right
UserControl uc4 = new UserControl()
{
Anchor = (AnchorStyles.Top | AnchorStyles.Right),
Height = resizeWidth,
Width = resizeWidth,
Left = this.DisplayRectangle.Width - resizeWidth,
Top = 0,
BackColor = Color.Transparent,
Cursor = Cursors.SizeNESW
};
uc4.MouseDown += form_MouseDown;
uc4.MouseUp += form_MouseUp;
uc4.MouseMove += delegate (object sender, MouseEventArgs e)
{
if (isDragging)
{
int diff = (e.Location.Y - lastRectangle.Y);
int y = (this.Location.Y + diff);
this.Location = new Point(this.Location.X, y);
this.Size = new Size(e.X - lastRectangle.X + this.Width, (this.Height + (diff * -1)));
}
};
uc4.BringToFront();
//uc4.BackColor = Color.Firebrick;
this.Controls.Add(uc4);
this.Controls.SetChildIndex(uc4, 0);
// top
UserControl uc5 = new UserControl()
{
Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right),
Height = resizeWidth,
Width = this.DisplayRectangle.Width - (resizeWidth * 2),
Left = resizeWidth,
Top = 0,
BackColor = Color.Transparent,
Cursor = Cursors.SizeNS
};
uc5.MouseDown += form_MouseDown;
uc5.MouseUp += form_MouseUp;
uc5.MouseMove += delegate (object sender, MouseEventArgs e)
{
if (isDragging)
{
int diff = (e.Location.Y - lastRectangle.Y);
int y = (this.Location.Y + diff);
this.Location = new Point(this.Location.X, y);
this.Size = new Size(lastRectangle.Width, (this.Height + (diff * -1)));
}
};
uc5.BringToFront();
this.Controls.Add(uc5);
this.Controls.SetChildIndex(uc5, 0);
// left
UserControl uc6 = new UserControl()
{
Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom),
Height = this.DisplayRectangle.Height - (resizeWidth * 2),
Width = resizeWidth,
Left = 0,
Top = resizeWidth,
BackColor = Color.Transparent,
Cursor = Cursors.SizeWE
};
uc6.MouseDown += form_MouseDown;
uc6.MouseUp += form_MouseUp;
uc6.MouseMove += delegate (object sender, MouseEventArgs e)
{
if (isDragging)
{
int diff = (e.Location.X - lastRectangle.X);
int x = (this.Location.X + diff);
this.Location = new Point(x, this.Location.Y);
this.Size = new Size((this.Width + (diff * -1)), this.Height);
}
};
uc6.BringToFront();
this.Controls.Add(uc6);
this.Controls.SetChildIndex(uc6, 0);
// bottom-left
UserControl uc7 = new UserControl()
{
Anchor = (AnchorStyles.Bottom | AnchorStyles.Left),
Height = resizeWidth,
Width = resizeWidth,
Left = 0,
Top = this.DisplayRectangle.Height - resizeWidth,
BackColor = Color.Transparent,
Cursor = Cursors.SizeNESW
};
uc7.MouseDown += form_MouseDown;
uc7.MouseUp += form_MouseUp;
uc7.MouseMove += delegate (object sender, MouseEventArgs e)
{
if (isDragging)
{
int diff = (e.Location.X - lastRectangle.X);
int x = (this.Location.X + diff);
this.Location = new Point(x, this.Location.Y);
this.Size = new Size((this.Width + (diff * -1)), (e.Y - lastRectangle.Y + this.Height));
}
};
uc7.BringToFront();
this.Controls.Add(uc7);
this.Controls.SetChildIndex(uc7, 0);
// bottom-left
UserControl uc8 = new UserControl()
{
Anchor = (AnchorStyles.Top | AnchorStyles.Left),
Height = resizeWidth,
Width = resizeWidth,
Left = 0,
Top = 0,
BackColor = Color.Transparent,
Cursor = Cursors.SizeNWSE
};
uc8.MouseDown += form_MouseDown;
uc8.MouseUp += form_MouseUp;
uc8.MouseMove += delegate (object sender, MouseEventArgs e)
{
if (isDragging)
{
int dX = (e.Location.X - lastRectangle.X);
int dY = (e.Location.Y - lastRectangle.Y);
int x = (this.Location.X + dX);
int y = (this.Location.Y + dY);
this.Location = new Point(x, y);
this.Size = new Size((this.Width + (dX * -1)), (this.Height + (dY * -1)));
}
};
uc8.BringToFront();
this.Controls.Add(uc8);
this.Controls.SetChildIndex(uc8, 0);
}
private void form_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
isDragging = true;
lastRectangle = new Rectangle(e.Location.X, e.Location.Y, this.Width, this.Height);
// If the mouse is within the dragging area
if (e.Y <= 30 && e.X <= this.Size.Width - 120)
canDrag = true;
}
}
private void form_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
// If we can drag the form
if (canDrag)
{
int x = (this.Location.X + (e.Location.X - lastRectangle.X));
int y = (this.Location.Y + (e.Location.Y - lastRectangle.Y));
this.Location = new Point(x, y);
}
}
}
private void form_MouseUp(object sender, MouseEventArgs e)
{
if (isDragging)
isDragging = false;
if (canDrag)
canDrag = false;
}
}
}
Does anybody know of a way to get rid of the flickering in the borderless form edges so it resembles the sizable form?
Edit: I've modified the code to use WndProc for resizing like Jimi stated and it still flickers in the same manner as the other code. I'm beginning to think the only way to stop the flickering is to use a sizable form. Does anybody have any ideas?
Form Constructor:
public MainForm()
{
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.None;
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.ResizeRedraw, true);
}
Edge Resize Code:
private const int HTLEFT = 10,
HTRIGHT = 11,
HTTOP = 12,
HTTOPLEFT = 13,
HTTOPRIGHT = 14,
HTBOTTOM = 15,
HTBOTTOMLEFT = 16,
HTBOTTOMRIGHT = 17,
HTCAPTION = 2;
const int edgeSize = 3; // you can rename this variable if you like
Rectangle Top { get { return new Rectangle(0, 0, this.ClientSize.Width, edgeSize); } }
Rectangle Left { get { return new Rectangle(0, 0, edgeSize, this.ClientSize.Height); } }
Rectangle Bottom { get { return new Rectangle(0, this.ClientSize.Height - edgeSize, this.ClientSize.Width, edgeSize); } }
Rectangle Right { get { return new Rectangle(this.ClientSize.Width - edgeSize, 0, edgeSize, this.ClientSize.Height); } }
Rectangle TopLeft { get { return new Rectangle(0, 0, edgeSize, edgeSize); } }
Rectangle TopRight { get { return new Rectangle(this.ClientSize.Width - edgeSize, 0, edgeSize, edgeSize); } }
Rectangle BottomLeft { get { return new Rectangle(0, this.ClientSize.Height - edgeSize, edgeSize, edgeSize); } }
Rectangle BottomRight { get { return new Rectangle(this.ClientSize.Width - edgeSize, this.ClientSize.Height - edgeSize, edgeSize, edgeSize); } }
protected override CreateParams CreateParams { get { var cp = base.CreateParams; cp.ExStyle |= 0x02000000; return cp; } }
protected override void OnPaint(PaintEventArgs e)
{
if (this.WindowState == FormWindowState.Normal)
{
Rectangle rc = new Rectangle(this.ClientSize.Width - cGrip, this.ClientSize.Height - cGrip, cGrip, cGrip);
ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
}
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x84)
{ // Trap WM_NCHITTEST
var cursor = this.PointToClient(Cursor.Position);
if (TopLeft.Contains(cursor)) m.Result = (IntPtr)HTTOPLEFT;
else if (TopRight.Contains(cursor)) m.Result = (IntPtr)HTTOPRIGHT;
else if (BottomLeft.Contains(cursor)) m.Result = (IntPtr)HTBOTTOMLEFT;
else if (BottomRight.Contains(cursor)) m.Result = (IntPtr)HTBOTTOMRIGHT;
else if (Top.Contains(cursor)) m.Result = (IntPtr)HTTOP;
else if (Left.Contains(cursor)) m.Result = (IntPtr)HTLEFT;
else if (Right.Contains(cursor)) m.Result = (IntPtr)HTRIGHT;
else if (Bottom.Contains(cursor)) m.Result = (IntPtr)HTBOTTOM;
else if (cursor.Y < cCaption) m.Result = (IntPtr)HTCAPTION;
}
}