如何调整平面窗口的大小?

时间:2019-01-25 16:32:52

标签: c# winforms

背景

你好我目前正在尝试在Windows窗体中为学校项目创建自定义平面样式窗口。想法是使用此窗口作为基础并创建从其继承的其他窗口。我试图实现的样式类似于Visual Studio 2017本身的样式(深色主题)。我正在尝试向窗口添加功能,例如:

  • 双击顶部面板将最大化窗口(完成)。
  • 使用顶部面板拖动窗口(完成)。
  • 聚焦/未聚焦(完成)时颜色改变边界。

尝试通过拖动边框使窗口可调整大小时出现问题。

我所拥有的:

这是window的图片。

该表单包含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;
    }
}}

但是,当我这样做时,矩形是在面板后面绘制的,因此即使我将矩形的大小(“ _”变量)设置为10px或20px,我可以单击以调整窗口大小的区域始终为1px (由于存在表格填充)。

我还尝试使用某种叠加层并在其中绘制矩形: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

2 个答案:

答案 0 :(得分:2)

您可以增加表格填充(将其设置为ex:2,2,2,2) 请检查:(Can't resize a borderless winform from top because of a docked panel

编辑:

与@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);
        }
    }

答案 1 :(得分:0)

我认为您的程序没有边界。你能把你的项目寄给我吗?