【问题标题】:How to move and resize a form without a border?如何移动和调整没有边框的表单?
【发布时间】:2010-04-04 17:21:55
【问题描述】:

有谁知道我如何在没有边框的情况下调整 winform 的大小。我不想要 Windows 的默认边框,所以我将属性“FormBorderStyle”更改为“None”。这删除了边框,虽然现在它不能调整大小。我已经想出了如何移动表单,我只需要知道如何调整它的大小。

【问题讨论】:

    标签: c# winforms resize border formborderstyle


    【解决方案1】:

    一些允许移动和调整表单大小的示例代码:

      public partial class Form1 : Form {
        public Form1() {
          InitializeComponent();
          this.FormBorderStyle = FormBorderStyle.None;
          this.DoubleBuffered = true;
          this.SetStyle(ControlStyles.ResizeRedraw, true);
        }
        private const int cGrip = 16;      // Grip size
        private const int cCaption = 32;   // Caption bar height;
    
        protected override void OnPaint(PaintEventArgs e) {
          Rectangle rc = new Rectangle(this.ClientSize.Width - cGrip, this.ClientSize.Height - cGrip, cGrip, cGrip);
          ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
          rc = new Rectangle(0, 0, this.ClientSize.Width, cCaption);
          e.Graphics.FillRectangle(Brushes.DarkBlue, rc);
        }
    
        protected override void WndProc(ref Message m) {
          if (m.Msg == 0x84) {  // Trap WM_NCHITTEST
            Point pos = new Point(m.LParam.ToInt32());
            pos = this.PointToClient(pos);
            if (pos.Y < cCaption) {
              m.Result = (IntPtr)2;  // HTCAPTION
              return;
            }
            if (pos.X >= this.ClientSize.Width - cGrip && pos.Y >= this.ClientSize.Height - cGrip) {
              m.Result = (IntPtr)17; // HTBOTTOMRIGHT
              return;
            }
          }
          base.WndProc(ref m);
        }
      }
    

    【讨论】:

    • 像这样我在顶部得到一个蓝色的丑陋条。
    • 如果您不希望栏位于顶部,请不要覆盖 OnPaint()。其余的代码是可靠的。谢谢一群朋友:)
    • 要移除顶部边框并且只使用尺寸控制,只需移除 OnPaint 方法的最后两行:rc = new Rectangle(0, 0, this.ClientSize.Width, cCaption); e.Graphics.FillRectangle(Brushes.DarkBlue, rc);
    • 我需要加入一些特别的东西吗?因为我不能让它工作。看起来 WndProc 被调用但 m.Msg 永远不会等于 0x84。 .NET 框架 4.8
    • 没关系。我的表单中有dock: fill 的面板,因此它完全覆盖了客户区域,鼠标始终悬停在控件上方,并且从未在客户区域,因此WM_NCHITTEST 从未触发...只需取消对接即可。
    【解决方案2】:

    这是一个完整的自定义表单示例,包含所有 8 个大小调整点:

    public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
      this.FormBorderStyle = FormBorderStyle.None; // no borders
      this.DoubleBuffered = true;
      this.SetStyle(ControlStyles.ResizeRedraw, true); // this is to avoid visual artifacts
    }
    
    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;
        }
    }}
    

    【讨论】:

    • 一个小错误。边和角是重叠的,因此例如返回 new Rectangle(0, 0, this.ClientSize.Width, _); 的顶部必须返回 new Rectangle(_, 0, this.ClientSize.Width - _, _); 以便为角正方形留下小正方形...其他边也将相应地具有偏移量
    • “错误”没有影响,因为在边缘之前检查了角落
    【解决方案3】:

    “Sizer”是右下角的浅蓝色面板

        int Mx;
        int My;
        int Sw;
        int Sh;
    
        bool mov;
    
        void SizerMouseDown(object sender, MouseEventArgs e)
        {
            mov = true;
            My = MousePosition.Y;
            Mx = MousePosition.X;
            Sw = Width;
            Sh = Height;
        }
    
        void SizerMouseMove(object sender, MouseEventArgs e)
        {
            if (mov == true) {
                Width = MousePosition.X - Mx + Sw;
                Height = MousePosition.Y - My + Sh;
            }
        }
    
        void SizerMouseUp(object sender, MouseEventArgs e)
        {
            mov = false;
        }
    

    【讨论】:

    • 一个不错的解决方案!但是,我没有使用蓝色面板,而是使用了一个小图片框来显示调整大小的点图案的图像,其中 Cursor 属性设置为“SizeAll”,这样当您在框上方时光标会变为调整箭头大小。
    【解决方案4】:

    (详细说明:在评论 2 中)

    从所有地方调整“表单”大小并移动它>>>完整代码

    //首先要添加这个类

     class ReSize
         {
    
            private bool Above, Right, Under, Left, Right_above, Right_under, Left_under, Left_above;
    
    
            int Thickness=6;  //Thickness of border  u can cheang it
            int Area = 8;     //Thickness of Angle border 
    
    
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="thickness">set thickness of form border</param>
            public ReSize(int thickness)
            {
                Thickness = thickness;
            }
    
            /// <summary>
            /// Constructor set thickness of form border=1
            /// </summary>
            public ReSize()
            {
                Thickness = 10;
            }
    
            //Get Mouse Position
            public  string getMosuePosition(Point mouse, Form form)
            {
                bool above_underArea = mouse.X > Area && mouse.X < form.ClientRectangle.Width - Area; /* |\AngleArea(Left_Above)\(=======above_underArea========)/AngleArea(Right_Above)/| */ //Area===>(==)
                bool right_left_Area = mouse.Y > Area && mouse.Y < form.ClientRectangle.Height - Area; 
    
                bool _Above=mouse.Y <= Thickness;  //Mouse in Above All Area
                bool _Right= mouse.X >= form.ClientRectangle.Width - Thickness;
                bool _Under=mouse.Y >= form.ClientRectangle.Height - Thickness;
                bool _Left=mouse.X <= Thickness;
    
                Above = _Above && (above_underArea); if (Above) return "a";   /*Mouse in Above All Area WithOut Angle Area */
                Right = _Right && (right_left_Area); if (Right) return "r";
                Under = _Under && (above_underArea); if (Under) return "u";
                Left = _Left && (right_left_Area);   if (Left) return "l";
    
    
                Right_above =/*Right*/ (_Right && (!right_left_Area)) && /*Above*/ (_Above && (!above_underArea));   if (Right_above) return "ra";     /*if Mouse  Right_above */
                Right_under =/* Right*/((_Right) && (!right_left_Area)) && /*Under*/(_Under && (!above_underArea));  if (Right_under) return "ru";     //if Mouse  Right_under 
                Left_under = /*Left*/((_Left) && (!right_left_Area)) && /*Under*/ (_Under && (!above_underArea));    if (Left_under) return "lu";      //if Mouse  Left_under
                Left_above = /*Left*/((_Left) && (!right_left_Area)) && /*Above*/(_Above && (!above_underArea));     if (Left_above) return "la";      //if Mouse  Left_above
    
                return "";
    
            }
    
    
        }
    

    然后形成cs

     public partial class FormGDI : Form
        {
    
            ReSize resize = new ReSize();     // ReSize Class "/\" To Help Resize Form <None Style>
    
    
            public FormGDI()
            {
                InitializeComponent();
                this.SetStyle(ControlStyles.ResizeRedraw, true);
    
            }
    
    
            private const int cGrip = 16;      // Grip size
            private const int cCaption = 32;   // Caption bar height;
    
            protected override void OnPaint(PaintEventArgs e)
            {
                //this if you want to draw   (if)
    
                Color theColor = Color.FromArgb(10, 20, 20, 20);
                theColor = Color.DarkBlue;
                int BORDER_SIZE = 4;
                ControlPaint.DrawBorder(e.Graphics, ClientRectangle,
                                             theColor, BORDER_SIZE, ButtonBorderStyle.Dashed,
                                             theColor, BORDER_SIZE, ButtonBorderStyle.Dashed,
                                             theColor, BORDER_SIZE, ButtonBorderStyle.Dashed,
                                             theColor, BORDER_SIZE, ButtonBorderStyle.Dashed);
    
    
                Rectangle rc = new Rectangle(this.ClientSize.Width - cGrip, this.ClientSize.Height - cGrip, cGrip, cGrip);
                ControlPaint.DrawSizeGrip(e.Graphics, this.BackColor, rc);
                rc = new Rectangle(0, 0, this.ClientSize.Width, cCaption);
                e.Graphics.FillRectangle(Brushes.DarkBlue, rc);
    
    
    
                base.OnPaint(e);
            }
    
    
            //set MinimumSize to Form
            public override Size MinimumSize
            {
                get
                {
                    return base.MinimumSize;
                }
                set
                {
                    base.MinimumSize = new Size(179, 51); 
                }
            }
    
            //
            //override  WndProc  
            //
            protected override void WndProc(ref Message m)
            {
                //****************************************************************************
    
                int x = (int)(m.LParam.ToInt64() & 0xFFFF);               //get x mouse position
                int y = (int)((m.LParam.ToInt64() & 0xFFFF0000) >> 16);   //get y mouse position  you can gave (x,y) it from "MouseEventArgs" too
                Point pt = PointToClient(new Point(x, y));
    
                if (m.Msg == 0x84)
                {
                    switch (resize.getMosuePosition(pt, this))
                    {
                        case "l": m.Result = (IntPtr)10; return;  // the Mouse on Left Form
                        case "r": m.Result = (IntPtr)11; return;  // the Mouse on Right Form
                        case "a": m.Result = (IntPtr)12; return;
                        case "la": m.Result = (IntPtr)13; return;
                        case "ra": m.Result = (IntPtr)14; return;
                        case "u": m.Result = (IntPtr)15; return;
                        case "lu": m.Result = (IntPtr)16; return;
                        case "ru": m.Result = (IntPtr)17; return; // the Mouse on Right_Under Form
                        case "": m.Result = pt.Y < 32 /*mouse on title Bar*/ ? (IntPtr)2 : (IntPtr)1; return;  
    
                    }
                }
    
                  base.WndProc(ref m);
    
            }
    
        }
    

    【讨论】:

    • 你能详细说明这是如何回答这个问题的吗?谢谢!
    • 详细说明:第一个 id 调整大小类它有一个方法来确定鼠标窗体的位置计算 (point mouse) 和 (Form form) 以获取窗体的宽度和高度,然后和最重要WndProc 覆盖方法这个方法有ref Message m 参数,当m.msg=0x84value 你可以设置m.result=10 这意味着你调用form 从左边调整大小和m.Result=11 从右边调用form 和.. ..到 17 但当 m.Result=2 you call to move the form` 和 m.Result=1that 意味着调用 don't do any thing
    • 它有帮助,但它不处理滚动,它会在滚动时通过表单创建新的边框“线条”
    【解决方案5】:

    最简单的方法是将鼠标事件分配给表单或标题栏,无论您想按住什么移动。 您可以通过将这些方法作为方法中的名称分配给那里的事件来移动无边框表单。

        int movX,movY;
        bool isMoving;
    
        private void onMouseDown(object sender, MouseEventArgs e)  
        {
             // Assign this method to mouse_Down event of Form or Panel,whatever you want
            isMoving = true;
            movX = e.X;
            movY = e.Y;
        }
    
        private void onMouseMove(object sender, MouseEventArgs e)
        {
             // Assign this method to Mouse_Move event of that Form or Panel
            if (isMoving)
            {
                this.SetDesktopLocation(MousePosition.X - movX, MousePosition.Y - movY);
            }
        }
    
        private void onMouseUp(object sender, MouseEventArgs e)
        {
           // Assign this method to Mouse_Up event of Form or Panel.
            isMoving = false;
        }
    

    【讨论】:

    • 位于第 2 行的 moxY 应替换为 movY
    【解决方案6】:

    如果您不介意顶部的短栏,您可以使用“常规”相当大的表单,将 .ControlBox 设置为 false 并将 .Text(顶部的标题栏)设置为空字符串.

    当您双击图表时,您最终会得到一个看起来像任务管理器的可调整大小的表单。 这种方法的优点是当你从左边调整它的大小时,右边框不会抖动。从顶部调整大小时也是如此。

    this.FormBorderStyle = FormBorderStyle.Sizable;
    this.ControlBox = false;
    this.Text = "";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-07
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 2015-12-30
      • 2016-05-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多