【问题标题】:How can user resize control at runtime in winforms用户如何在运行时在 winforms 中调整控件大小
【发布时间】:2013-06-23 19:02:24
【问题描述】:

假设我有一个图片框。

现在我想要的是用户应该能够随意调整图片框的大小。但是我不知道如何开始这件事。我在网上搜索过,但信息很少。

谁能指导我从哪里开始?

【问题讨论】:

    标签: c# .net winforms


    【解决方案1】:

    这很容易做到,Windows 中的每个窗口都具有可调整大小的先天能力。它刚刚为 PictureBox 关闭,您可以通过收听 WM_NCHITTEST message 将其重新打开。您只需告诉 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 中放置控件时所做的那样。
    • 我非常喜欢这个答案。关于@WinCoder 提到的限制,如果在cp.Style |= 0x840000; 行中将值0x840000 替换为0x00040000,则可以使用第二种解决方案从控件的任何一侧调整大小。这会将样式设置为 WS_SIZEBOX 。 Reference Here
    【解决方案2】:

    这是一篇文章

    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();
        }
    
    }
    

    【讨论】:

    • 好吧,我更愿意实现自己的解决方案,但从代码的外观来看,它似乎超出了我的能力范围。
    • 它并不像听起来那么简单,因为由于您在运行时执行此操作,因此您必须在运行时更新控件并跟踪我认为此解决方案很简单的点
    • 我真的更愿意实现我自己的解决方案,用 XAML 更容易吗?
    • 抱歉,据我所知,该类无法正常工作,因为接近尾声的开关在每种情况下都有设计时错误
    • 您能在这里尝试修改您的代码吗?似乎你做了一些工作,但它像这样失败了——即使我用 if、else if... 块替换失败的 Case 语句。
    【解决方案3】:

    使用this article 中的 ControlMoverOrResizer 类,您可以在运行时执行可移动和可调整大小的控件,只需一行代码! :) 例子:

    ControlMoverOrResizer.Init(button1);

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

    【讨论】:

      【解决方案4】:

      创建一个新的 c# winform 应用程序并粘贴:

      帮到你的时候别忘了说声谢谢……

      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

      【讨论】:

        【解决方案5】:
        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 应用程序中的某个面板

        【讨论】:

          猜你喜欢
          • 2010-12-20
          • 2011-04-24
          • 2013-07-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-10
          相关资源
          最近更新 更多