用户如何在winforms中运行时调整控件大小

16

假设我有一个pictureBox。

现在我的要求是用户可以随意调整pictureBox的大小。然而,我甚至不知道如何开始这件事情。我已经在互联网上搜索过,但信息很少。

是否有人至少可以指导我从哪里开始?

6个回答

42

这很容易做到,在Windows中的每个窗口都具有可调整大小的固有能力。PictureBox可以关闭该功能,但您可以通过监听WM_NCHITTEST消息来重新打开它。您只需告诉Windows光标位于窗口角落,就可以免费获得其他所有内容。您还需要绘制一个抓取手柄,以便清楚地向用户表示拖动角落将调整框的大小。

向项目添加一个新类,并粘贴下面显示的代码。 构建+构建。 您将在工具箱的顶部获得一个新控件,将其放置在表单上。 设置Image属性即可尝试它。

using System;
using System.Drawing;
using System.Windows.Forms;

class SizeablePictureBox : PictureBox {
    public SizeablePictureBox() {
        this.ResizeRedraw = true;
    }
    protected override void OnPaint(PaintEventArgs e) {
        base.OnPaint(e);
        var rc = new Rectangle(this.ClientSize.Width - grab, this.ClientSize.Height - grab, grab, grab);
        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 pos = this.PointToClient(new Point(m.LParam.ToInt32()));
            if (pos.X >= this.ClientSize.Width - grab && pos.Y >= this.ClientSize.Height - grab)
                m.Result = new IntPtr(17);  // HT_BOTTOMRIGHT
        }
    }
    private const int grab = 16;
}

另一个非常便宜的免费调整大小的方法是通过给控件添加可调整大小的边框。该方法适用于所有角落和边缘。将以下代码粘贴到类中即可(您不再需要WndProc):

protected override CreateParams CreateParams {
    get {
        var cp = base.CreateParams;
        cp.Style |= 0x840000;  // Turn on WS_BORDER + WS_THICKFRAME
        return cp;
    }
}

好的,现在我能够在运行时调整控件的大小了。然而,调整大小的手柄只出现在控件的右下角。有没有办法让我可以从任何位置调整控件的大小,就像在 Visual Studio 中放置控件时那样? - Win Coder
2
我非常喜欢这个答案。关于@WinCoder提到的限制,如果在行cp.Style |= 0x840000;中将值0x840000替换为0x00040000,则可以使用第二种解决方案从控件的任何一侧调整大小。这将设置样式为WS_SIZEBOX。参考链接 - u8it

6

这篇文章中,使用ControlMoverOrResizer类,您只需要一行代码就可以在运行时实现可移动和可调整大小的控件! :) 示例:

ControlMoverOrResizer.Init(button1);

现在button1是一个可移动和可调整大小的控件!


4

这是一篇关于IT技术的文章:

http://www.codeproject.com/Articles/20716/Allow-the-User-to-Resize-Controls-at-Runtime

它主要介绍了如何在运行时调整控件大小的方法,如果你使用VB开发,该文章对你会有所帮助。如果你使用C#进行开发,则可以参考其翻译。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class Form1
{


    ResizeableControl rc;

    private void Form1_Load(System.Object sender, System.EventArgs e)
    {
        rc = new ResizeableControl(pbDemo);

    }
    public Form1()
    {
        Load += Form1_Load;
    }

}

并且重新调整大小的功能

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class ResizeableControl
{

    private Control withEventsField_mControl;
    private Control mControl {
        get { return withEventsField_mControl; }
        set {
            if (withEventsField_mControl != null) {
                withEventsField_mControl.MouseDown -= mControl_MouseDown;
                withEventsField_mControl.MouseUp -= mControl_MouseUp;
                withEventsField_mControl.MouseMove -= mControl_MouseMove;
                withEventsField_mControl.MouseLeave -= mControl_MouseLeave;
            }
            withEventsField_mControl = value;
            if (withEventsField_mControl != null) {
                withEventsField_mControl.MouseDown += mControl_MouseDown;
                withEventsField_mControl.MouseUp += mControl_MouseUp;
                withEventsField_mControl.MouseMove += mControl_MouseMove;
                withEventsField_mControl.MouseLeave += mControl_MouseLeave;
            }
        }
    }
    private bool mMouseDown = false;
    private EdgeEnum mEdge = EdgeEnum.None;
    private int mWidth = 4;

    private bool mOutlineDrawn = false;
    private enum EdgeEnum
    {
        None,
        Right,
        Left,
        Top,
        Bottom,
        TopLeft
    }

    public ResizeableControl(Control Control)
    {
        mControl = Control;
    }


    private void mControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left) {
            mMouseDown = true;
        }
    }


    private void mControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        mMouseDown = false;
    }


    private void mControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        Control c = (Control)sender;
        Graphics g = c.CreateGraphics;
        switch (mEdge) {
            case EdgeEnum.TopLeft:
                g.FillRectangle(Brushes.Fuchsia, 0, 0, mWidth * 4, mWidth * 4);
                mOutlineDrawn = true;
                break;
            case EdgeEnum.Left:
                g.FillRectangle(Brushes.Fuchsia, 0, 0, mWidth, c.Height);
                mOutlineDrawn = true;
                break;
            case EdgeEnum.Right:
                g.FillRectangle(Brushes.Fuchsia, c.Width - mWidth, 0, c.Width, c.Height);
                mOutlineDrawn = true;
                break;
            case EdgeEnum.Top:
                g.FillRectangle(Brushes.Fuchsia, 0, 0, c.Width, mWidth);
                mOutlineDrawn = true;
                break;
            case EdgeEnum.Bottom:
                g.FillRectangle(Brushes.Fuchsia, 0, c.Height - mWidth, c.Width, mWidth);
                mOutlineDrawn = true;
                break;
            case EdgeEnum.None:
                if (mOutlineDrawn) {
                    c.Refresh();
                    mOutlineDrawn = false;
                }
                break;
        }

        if (mMouseDown & mEdge != EdgeEnum.None) {
            c.SuspendLayout();
            switch (mEdge) {
                case EdgeEnum.TopLeft:
                    c.SetBounds(c.Left + e.X, c.Top + e.Y, c.Width, c.Height);
                    break;
                case EdgeEnum.Left:
                    c.SetBounds(c.Left + e.X, c.Top, c.Width - e.X, c.Height);
                    break;
                case EdgeEnum.Right:
                    c.SetBounds(c.Left, c.Top, c.Width - (c.Width - e.X), c.Height);
                    break;
                case EdgeEnum.Top:
                    c.SetBounds(c.Left, c.Top + e.Y, c.Width, c.Height - e.Y);
                    break;
                case EdgeEnum.Bottom:
                    c.SetBounds(c.Left, c.Top, c.Width, c.Height - (c.Height - e.Y));
                    break;
            }
            c.ResumeLayout();
        } else {
            switch (true) {
                case e.X <= (mWidth * 4) & e.Y <= (mWidth * 4):
                    //top left corner
                    c.Cursor = Cursors.SizeAll;
                    mEdge = EdgeEnum.TopLeft;
                    break;
                case e.X <= mWidth:
                    //left edge
                    c.Cursor = Cursors.VSplit;
                    mEdge = EdgeEnum.Left;
                    break;
                case e.X > c.Width - (mWidth + 1):
                    //right edge
                    c.Cursor = Cursors.VSplit;
                    mEdge = EdgeEnum.Right;
                    break;
                case e.Y <= mWidth:
                    //top edge
                    c.Cursor = Cursors.HSplit;
                    mEdge = EdgeEnum.Top;
                    break;
                case e.Y > c.Height - (mWidth + 1):
                    //bottom edge
                    c.Cursor = Cursors.HSplit;
                    mEdge = EdgeEnum.Bottom;
                    break;
                default:
                    //no edge
                    c.Cursor = Cursors.Default;
                    mEdge = EdgeEnum.None;
                    break;
            }
        }
    }


    private void mControl_MouseLeave(object sender, System.EventArgs e)
    {
        Control c = (Control)sender;
        mEdge = EdgeEnum.None;
        c.Refresh();
    }

}

我本来更喜欢实现自己的解决方案,但看起来这段代码似乎超出了我的能力范围。 - Win Coder
这并不像听起来那么简单,因为你是在运行时进行操作,所以你必须在运行时更新控件并跟踪点。我认为这个解决方案很简单。 - COLD TOLD
我真的更喜欢实现自己的解决方案,XAML 中做起来更容易吗? - Win Coder
抱歉,据我所知这个类似乎无法工作,因为最后的开关在每个情况下都有设计时错误。 - Daniel Casserly
请问您能否尝试修改一下您的代码?看起来您已经花了不少心思在它上面,但是它仍然存在问题——即使我用 if、else if 语句块替换掉了出错的 Case 语句。 - ElDoRado1239

2
创建一个新的C# Windows窗体应用程序并粘贴以下内容:
不要忘记在它帮助你时说声谢谢... http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=743923&av=1095793&msg=4778687
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
  {
 public partial class MyForm : Form
  {
    //Public Declaration:
    double rW = 0;
    double rH = 0;

    int fH = 0;
    int fW = 0;


    // @ Form Initialization
    public MyForm()
    {
        InitializeComponent();
        this.Resize += MyForm_Resize; // handles resize routine
        this.tabControl1.Dock = DockStyle.None;

    }


    private void MyForm_Resize(object sender, EventArgs e)
    {
        rResize(this,true); //Call the routine

    }

    private void rResize(Control t, bool hasTabs) // Routine to Auto resize the control
    {

        // this will return to normal default size when 1 of the conditions is met

        string[] s = null;

        if (this.Width < fW || this.Height < fH)
        {

            this.Width = (int)fW;
            this.Height = (int)fH;

            return;
        }

        foreach (Control c in t.Controls)
        {
            // Option 1:
            double rRW = (t.Width > rW ? t.Width / (rW) : rW / t.Width);
            double rRH = (t.Height > rH ? t.Height / (rH) : rH / t.Height);

            // Option 2:
            //  double rRW = t.Width / rW;
            //  double rRH = t.Height / rH;

            s = c.Tag.ToString().Split('/');
            if (c.Name == s[0].ToString())
            {
                //Use integer casting
                c.Width = (int)(Convert.ToInt32(s[3]) * rRW);
                c.Height = (int)(Convert.ToInt32(s[4]) * rRH);
                c.Left = (int)(Convert.ToInt32(s[1]) * rRW);
                c.Top = (int)(Convert.ToInt32(s[2]) * rRH);
            }
            if (hasTabs)
            {
                if (c.GetType() == typeof(TabControl))
                {

                    foreach (Control f in c.Controls)
                    {
                        foreach (Control j in f.Controls) //tabpage
                        {
                            s = j.Tag.ToString().Split('/');

                            if (j.Name == s[0].ToString())
                            {

                                j.Width = (int)(Convert.ToInt32(s[3]) * rRW);
                                j.Height = (int)(Convert.ToInt32(s[4]) * rRH);
                                j.Left = (int)(Convert.ToInt32(s[1]) * rRW);
                                j.Top = (int)(Convert.ToInt32(s[2]) * rRH);
                            }
                        }
                    }
                }
            }

        }
    }

    // @ Form Load Event
    private void MyForm_Load(object sender, EventArgs e)
    {


        // Put values in the variables

        rW = this.Width;
        rH = this.Height;

        fW = this.Width;
        fH = this.Height;


        // Loop through the controls inside the  form i.e. Tabcontrol Container
        foreach (Control c in this.Controls)
        {
            c.Tag = c.Name + "/" + c.Left + "/" + c.Top + "/" + c.Width + "/" + c.Height;

            // c.Anchor = (AnchorStyles.Right |  AnchorStyles.Left ); 

            if (c.GetType() == typeof(TabControl))
            {

                foreach (Control f in c.Controls)
                {

                    foreach (Control j in f.Controls) //tabpage
                    {
                        j.Tag = j.Name + "/" + j.Left + "/" + j.Top + "/" + j.Width + "/" + j.Height;
                    }
                }
            }
        }
    }
}
}

您好,Kix46:


1
namespace utils
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Data;
using System.Globalization;
using System.Xml;
using System.Text.RegularExpressions;
using System.Drawing;
public static class Helper
{
    public const int WM_NCLBUTTONDOWN = 0xA1;
    public const int HTCAPTION = 2;
    public static int WS_THICKFRAME = 0x00040000;
    public static int GWL_STYLE = -16;
    public static int GWL_EXSTYLE = -20;
    public static int WS_EX_LAYERED = 0x00080000;
    public const int WS_RESIZABLE = 0x840000; //WS_BORDER + WS_THICKFRAME

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    static extern bool AppendMenu(IntPtr hMenu, uint uFlags, uint uIDNewItem, string lpNewItem);

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern int
    SetLayeredWindowAttributes(IntPtr Handle, int Clr, byte transparency, int clrkey);

    [System.Runtime.InteropServices.DllImport("shell32.dll")]
    public static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);

    [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    public static extern bool PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    public static extern uint GetCurrentThreadId();
    public static string ProcessException(this Exception ex)
    {
        StringBuilder strBuild = new StringBuilder(5000);
        Exception inner = ex;
        Enumerable.Range(0, 30).All(x =>
        {
            if (x == 0) strBuild.Append("########## Exception begin on thread id : " + GetCurrentThreadId().ToString() + " @ :" + DateTime.Now.ToString() + " ##########\n");
            strBuild.Append("---------------------[" + x.ToString() + "]---------------------\n");
            strBuild.Append("Message : " + inner.Message + "\nStack Trace : " + inner.StackTrace + "\n");
            strBuild.Append("---------------------[" + x.ToString() + "]---------------------\n");
            inner = inner.InnerException;
            if (inner == null)
            {
                strBuild.Append("########## Exception End on thread id : " + GetCurrentThreadId().ToString() + " @ :" + DateTime.Now.ToString() + " ##########\n\n");
                return false;
            }
            return true;
        });
        return strBuild.ToString();
    }
   
   public static void MakeResizable(this Panel pnl)
    {
        int dwCurStyle = Helper.GetWindowLong(pnl.Handle, GWL_STYLE);
        dwCurStyle = dwCurStyle | Helper.WS_RESIZABLE;
        Helper.SetWindowLong(pnl.Handle, GWL_STYLE, dwCurStyle);
    }
}

 protected override void OnLoad(EventArgs e)
    {
        imagePanel.MakeResizable();
        base.OnLoad(e);            
    }

其中imgPanel是WinForm应用程序中的某个面板


0
我在我的Windows窗体应用程序中完成了这个任务。
public partial class logoPosition : Form
    {
        bool Draggable = false, ResizableH = false, ResizableW = false;
        int XOffset = 0, YOffset = 0;
        public logoPosition()
        {
            InitializeComponent();
        }

        private void logoPosition_Load(object sender, EventArgs e)
        {
            Image logo = new Bitmap(@"\Sign_Transparent.png");
            PBLogo.Image = logo;
            PBLogo.Margin = new Padding(3);
            PBLogo.Location = new Point(3, 3);
            PBLogo.BorderStyle = BorderStyle.FixedSingle;
            PBLogo.SizeMode = PictureBoxSizeMode.StretchImage;
            txtW.Text = PBLogo.Width.ToString();
            txtH.Text = PBLogo.Height.ToString();
            txtX.Text = PBLogo.Location.X.ToString();
            txtY.Text = PBLogo.Location.Y.ToString();
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            PBLogo.Margin = new Padding(3);
            PBLogo.Location = new Point(3, 3);
            PBLogo.BorderStyle = BorderStyle.FixedSingle;
            PBLogo.SizeMode = PictureBoxSizeMode.StretchImage;
            PBLogo.Height = 50;
            PBLogo.Width = 100;
        }

        private void PBLogo_MouseMove(object sender, MouseEventArgs e)
        {

            //set location for PictureBox bottom side;
            Rectangle recBottomSide = new Rectangle(0 ,  PBLogo.Height-3, PBLogo.Width,10);
            //set location for PictureBox right side;
            Rectangle recRightSide = new Rectangle(PBLogo.Width-3, 0, 10, PBLogo.Height);
            

            if (recBottomSide.Contains(e.Location))
            {
                PBLogo.Cursor = Cursors.SizeNS;
            }
            else if(recRightSide.Contains(e.Location))
            {
                PBLogo.Cursor = Cursors.SizeWE;
            }
            else
            {
                PBLogo.Cursor = Cursors.SizeAll;
            }

            int XMoved = e.Location.X - XOffset;
            int YMoved = e.Location.Y - YOffset;
            Point newPosition = new Point();

            if (Draggable)
            {

                newPosition.X = PBLogo.Location.X + XMoved;
                newPosition.Y = PBLogo.Location.Y + YMoved;

                if (newPosition.X + PBLogo.Width >= panel1.Width || newPosition.X <= 0)
                    newPosition.X = PBLogo.Location.X;
                if (newPosition.Y + PBLogo.Height > panel1.Height || newPosition.Y <= 0)
                    newPosition.Y = PBLogo.Location.Y;

                PBLogo.Location = newPosition;
                
            }
            if(ResizableH)
            {
                if (PBLogo.Location.Y + e.Y < panel1.Height)
                {
                    PBLogo.Height = e.Y;
                    if (PBLogo.Height < 30) PBLogo.Height = 30;
                }
            }
            if(ResizableW)
            {
                if (PBLogo.Location.X + e.X < panel1.Width)
                {
                    PBLogo.Width = e.X;
                    if (PBLogo.Width < 30) PBLogo.Width = 30;
                }
            }


            txtW.Text = PBLogo.Width.ToString();
            txtH.Text = PBLogo.Height.ToString();
            txtX.Text = PBLogo.Location.X.ToString();
            txtY.Text = PBLogo.Location.Y.ToString();

            

            
        }

        private void PBLogo_MouseDown(object sender, MouseEventArgs e)
        {
            XOffset = e.X;
            YOffset = e.Y;

            if (PBLogo.Cursor == Cursors.SizeAll)
            {
                Draggable = true;
                ResizableW = false;
                ResizableH = false;
            }
            if(PBLogo.Cursor == Cursors.SizeNS)
            {
                Draggable = false;
                ResizableW = false;
                ResizableH = true;
            }
            if (PBLogo.Cursor == Cursors.SizeWE)
            {
                Draggable = false;
                ResizableW = true;
                ResizableH = false;
            }

        }

        private void PBLogo_MouseUp(object sender, MouseEventArgs e)
        {
            Draggable = false;
            ResizableW = false;
            ResizableH = false;
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接