Как я могу изменить размер плоского окна? - PullRequest
0 голосов
/ 25 января 2019

Справочная информация:

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

1 Ответ

0 голосов
/ 25 января 2019

Вы можете увеличить заполнение форм (установите его на, например: 2,2,2,2). Проверьте: ( Невозможно изменить размер winform без полей сверху из-за закрепленной панели )

Редактировать:

, как и в той же ссылке, что @Outman предложил изменить цвет границы:

        protected override void OnPaintBackground(PaintEventArgs e)
    {
        base.OnPaintBackground(e);            //comment this out to prevent default painting 
        using (SolidBrush brush = new SolidBrush(Color.FromArgb(45, 45, 48))) //any color you like  }
        {
            e.Graphics.FillRectangle(brush, e.ClipRectangle);
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...