Справочная информация:
Hello. В настоящее время я пытаюсь создать собственное плоское окно в Windows Forms для школьного проекта. Идея состоит в том, чтобы использовать это окно в качестве основы и создавать другие окна, которые наследуются от него. Стиль, которого я пытаюсь достичь, похож на стиль самой Visual Studio 2017 (темная тема). Я пытаюсь добавить функциональность в окно, например:
- Двойной щелчок по верхней панели увеличивает окно (Готово).
- Перетаскивание окна с верхней панели (Готово).
- Изменение цвета границы, когда фокус / расфокусировка (Готово).
Проблема возникает при попытке изменить размер окна путем перетаскивания границ.
Что у меня есть:
Вот изображение окна .
Форма имеет 2 панели:
- Верхняя панель: значок в виде окна, метка для названия окна и 3 кнопки (свернуть, развернуть и закрыть).
- Основная панель: это пустая панель, в которой будет находиться содержимое окна.
Форма имеет отступ 1px (граница изменения цвета, это появится позже)
Проблема:
Я нашел ответ, который, казалось, решил мою проблему: https://stackoverflow.com/a/32261547/70345, но когда я пытаюсь реализовать его, он не работает полностью. Кажется, что люди делают рисование прямоугольников вокруг формы и обнаруживают в функции WndProc, находится ли курсор над ними:
protected override void OnPaint(PaintEventArgs e) // you can safely omit this method if you want
{
e.Graphics.FillRectangle(Brushes.Green, Top);
e.Graphics.FillRectangle(Brushes.Green, Left);
e.Graphics.FillRectangle(Brushes.Green, Right);
e.Graphics.FillRectangle(Brushes.Green, Bottom);
}
private const int
HTLEFT = 10,
HTRIGHT = 11,
HTTOP = 12,
HTTOPLEFT = 13,
HTTOPRIGHT = 14,
HTBOTTOM = 15,
HTBOTTOMLEFT = 16,
HTBOTTOMRIGHT = 17;
const int _ = 10; // you can rename this variable if you like
Rectangle Top { get { return new Rectangle(0, 0, this.ClientSize.Width, _); } }
Rectangle Left { get { return new Rectangle(0, 0, _, this.ClientSize.Height); } }
Rectangle Bottom { get { return new Rectangle(0, this.ClientSize.Height - _, this.ClientSize.Width, _); } }
Rectangle Right { get { return new Rectangle(this.ClientSize.Width - _, 0, _, this.ClientSize.Height); } }
Rectangle TopLeft { get { return new Rectangle(0, 0, _, _); } }
Rectangle TopRight { get { return new Rectangle(this.ClientSize.Width - _, 0, _, _); } }
Rectangle BottomLeft { get { return new Rectangle(0, this.ClientSize.Height - _, _, _); } }
Rectangle BottomRight { get { return new Rectangle(this.ClientSize.Width - _, this.ClientSize.Height - _, _, _); } }
protected override void WndProc(ref Message message)
{
base.WndProc(ref message);
if (message.Msg == 0x84) // WM_NCHITTEST
{
var cursor = this.PointToClient(Cursor.Position);
if (TopLeft.Contains(cursor)) message.Result = (IntPtr)HTTOPLEFT;
else if (TopRight.Contains(cursor)) message.Result = (IntPtr)HTTOPRIGHT;
else if (BottomLeft.Contains(cursor)) message.Result = (IntPtr)HTBOTTOMLEFT;
else if (BottomRight.Contains(cursor)) message.Result = (IntPtr)HTBOTTOMRIGHT;
else if (Top.Contains(cursor)) message.Result = (IntPtr)HTTOP;
else if (Left.Contains(cursor)) message.Result = (IntPtr)HTLEFT;
else if (Right.Contains(cursor)) message.Result = (IntPtr)HTRIGHT;
else if (Bottom.Contains(cursor)) message.Result = (IntPtr)HTBOTTOM;
}
}}
Но когда я это делаю, прямоугольники рисуются за панелями, поэтому даже если я установлю размер прямоугольника (переменная "_") равным 10 или 20 пикселям, область, в которой я могу щелкнуть, чтобы изменить размер окна, всегда равна 1 пикселю. (из-за заполнения формы).
Я также пытался использовать какое-то наложение и рисовать там прямоугольники: https://www.codeproject.com/Articles/26071/Draw-Over-WinForms-Controls
Но у меня была такая же проблема.
Что мне нужно:
Мне нужно как-то нарисовать прямоугольники перед панелями, чтобы у меня была большая площадь для изменения размера формы. Я не очень опытный в программировании, поэтому я открыт для любых предложений и улучшений. Также приветствуются альтернативные решения.
Это моя форма:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BaseWindow
{
public partial class BaseWindowForm : Form
{
public BaseWindowForm()
{
InitializeComponent();
}
#region draggable window
private bool windowDragging = false;
private Point startPoint = new Point(0, 0);
private void TopPanel_MouseDown(object sender, MouseEventArgs e)
{
windowDragging = true; // _dragging is your variable flag
startPoint = new Point(e.X, e.Y);
}
private void TopPanel_MouseUp(object sender, MouseEventArgs e)
{
windowDragging = false;
}
private void TopPanel_MouseMove(object sender, MouseEventArgs e)
{
if (windowDragging)
{
Point p = PointToScreen(e.Location);
Location = new Point(p.X - this.startPoint.X, p.Y - this.startPoint.Y);
}
}
#endregion
#region border color focus
private void BaseWindowForm_Activated(object sender, EventArgs e)
{
this.BackColor = Color.FromArgb(0, 122, 204);
}
private void BaseWindowForm_Deactivate(object sender, EventArgs e)
{
this.BackColor = Color.FromArgb(63, 63, 70);
}
#endregion
#region maximize/minimize
private void BaseWindowForm_Maximize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Normal)
{
this.WindowState = FormWindowState.Maximized;
}
else if (this.WindowState == FormWindowState.Maximized)
{
this.WindowState = FormWindowState.Normal;
}
}
private void ButtonMinimize_Click(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Minimized;
}
#endregion
private const int
HTLEFT = 10,
HTRIGHT = 11,
HTTOP = 12,
HTTOPLEFT = 13,
HTTOPRIGHT = 14,
HTBOTTOM = 15,
HTBOTTOMLEFT = 16,
HTBOTTOMRIGHT = 17;
const int _ = 10; // you can rename this variable if you like
Rectangle Top { get { return new Rectangle(0, 0, this.ClientSize.Width, _); } }
Rectangle Left { get { return new Rectangle(0, 0, _, this.ClientSize.Height); } }
Rectangle Bottom { get { return new Rectangle(0, this.ClientSize.Height - _, this.ClientSize.Width, _); } }
Rectangle Right { get { return new Rectangle(this.ClientSize.Width - _, 0, _, this.ClientSize.Height); } }
Rectangle TopLeft { get { return new Rectangle(0, 0, _, _); } }
Rectangle TopRight { get { return new Rectangle(this.ClientSize.Width - _, 0, _, _); } }
Rectangle BottomLeft { get { return new Rectangle(0, this.ClientSize.Height - _, _, _); } }
Rectangle BottomRight { get { return new Rectangle(this.ClientSize.Width - _, this.ClientSize.Height - _, _, _); } }
protected override void WndProc(ref Message message)
{
base.WndProc(ref message);
if (message.Msg == 0x84) // WM_NCHITTEST
{
var cursor = this.PointToClient(Cursor.Position);
if (TopLeft.Contains(cursor)) message.Result = (IntPtr)HTTOPLEFT;
else if (TopRight.Contains(cursor)) message.Result = (IntPtr)HTTOPRIGHT;
else if (BottomLeft.Contains(cursor)) message.Result = (IntPtr)HTBOTTOMLEFT;
else if (BottomRight.Contains(cursor)) message.Result = (IntPtr)HTBOTTOMRIGHT;
else if (Top.Contains(cursor)) message.Result = (IntPtr)HTTOP;
else if (Left.Contains(cursor)) message.Result = (IntPtr)HTLEFT;
else if (Right.Contains(cursor)) message.Result = (IntPtr)HTRIGHT;
else if (Bottom.Contains(cursor)) message.Result = (IntPtr)HTBOTTOM;
}
}
}
}
Если вам нужна дополнительная информация, вы можете скачать исходный код здесь: https://github.com/RndmDud/FormBaseWindow