【问题标题】:How to set minimum Size of Custom Control with "CreateParams"如何使用“CreateParams”设置自定义控件的最小大小
【发布时间】:2020-06-19 14:59:16
【问题描述】:

我正在尝试制作一个可拖动具有最小尺寸的可调整大小的面板。我使用CreateParams 调整大小,现在Minimum 大小属性不起作用。

我的问题是这种情况下如何设置最小尺寸?

我已尝试Limit resizable dimensions of a custom control (c# .net),但无法正常工作。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Move_Resize_Controls
{
    class MyPanel: Panel
    {
        // For Moving Panel "Drag the Titlebar and move the panel"
        public const int WM_NCLBUTTONDOWN = 0xA1;
        public const int HT_CAPTION = 0x2;

        [DllImportAttribute("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd,
                         int Msg, int wParam, int lParam);
        [DllImportAttribute("user32.dll")]
        public static extern bool ReleaseCapture();

        // Constructor
        public MyPanel()
        {
            typeof(MyPanel).InvokeMember("DoubleBuffered", BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, this, new object[] { true }); // Double buffer MyPanel
            TitleBar(); // TitleBar
        }

        // Resize function for the panel - "Resizable Panel"
        protected override CreateParams CreateParams
        {
            get
            {
                var cp = base.CreateParams;
                cp.Style |= (int)0x00040000L;  // Turn on WS_BORDER + WS_THICKFRAME
                //cp.Style |= (int)0x00C00000L;  // Move
                return cp;
            }
        }

        // The Title Bar
        private void TitleBar()
        {
            Panel titleBar = new Panel();
            titleBar.BackColor = Color.Black;
            titleBar.Size = new Size(this.Size.Width, 20);
            titleBar.Dock = DockStyle.Top;
            this.Controls.Add(titleBar);

            titleBar.MouseDown  += new System.Windows.Forms.MouseEventHandler(this.MouseDownTitleBar); // Mouse Down - Event
            typeof(Panel).InvokeMember("DoubleBuffered", BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, titleBar, new object[] { true }); // Double Buffered 
        }

        // Move Panel
        private void MouseDownTitleBar(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                ReleaseCapture();
                SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
            }
        }
    }
}

【问题讨论】:

    标签: c# winforms custom-controls resizable createparams


    【解决方案1】:

    MinimumSize() 属性设置为您想要的控件(正常通过IDE 或通过代码),然后将下面的代码添加到控件以捕获WM_GETMINMAXINFO 消息并覆盖控件的最小大小动态调整大小:

    class MyPanel: Panel
    {
    
        public const int WM_GETMINMAXINFO = 0x24;
    
        public struct POINTAPI
        {
            public Int32 X;
            public Int32 Y;
        }
    
        public struct MINMAXINFO
        {
            public POINTAPI ptReserved;
            public POINTAPI ptMaxSize;
            public POINTAPI ptMaxPosition;
            public POINTAPI ptMinTrackSize;
            public POINTAPI ptMaxTrackSize;
        }
    
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_GETMINMAXINFO:
                    MINMAXINFO mmi = (MINMAXINFO)System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, typeof(MINMAXINFO));
                    mmi.ptMinTrackSize.X = this.MinimumSize.Width;
                    mmi.ptMinTrackSize.Y = this.MinimumSize.Height;
                    System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, m.LParam, true);
                    break;
            }
            base.WndProc(ref m);
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      只需设置 MinimumSize 属性:

      这里的这个类是我的一个 Nuget 包的一部分。我在构造函数中添加了这个 MinimumSize 只是为了向你展示,我通常在代码中没有这个:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows.Forms;
      
      namespace DataJuggler.Win.Controls.Objects
      {
      
          #region class PanelExtender : Panel
          /// <summary>
          /// This class inherits from Panel; this is intended to stop the flickering on panels
          /// </summary>
          public class PanelExtender : Panel
          {
      
              #region Constructor
              /// <summary>
              /// Create a new instance of a PanelExtender object
              /// </summary>
              public PanelExtender()
              {
                  // Set Style to stop flickering
                  this.SetStyle(System.Windows.Forms.ControlStyles.UserPaint | System.Windows.Forms.ControlStyles.AllPaintingInWmPaint | System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer, true);
      
                  // Set the minimum size
                  this.MinimumSize = new System.Drawing.Size(400, 800);
              }
              #endregion
      
              #region Properties
      
                  #region CreateParams
                  /// <summary>
                  /// This property here is what did the trick to reduce the flickering.
                  /// I also needed to make all of the controls Double Buffered, but
                  /// this was the final touch. It is a little slow when you switch tabs
                  /// but that is because the repainting is finishing before control is
                  /// returned.
                  /// </summary>
                  protected override CreateParams CreateParams
                  {
                      get
                      {
                          // initial value
                          CreateParams cp = base.CreateParams;
      
                          // Apparently this interrupts Paint to finish before showing
                          cp.ExStyle |= 0x02000000;
      
                          // return value
                          return cp;
                      }
                  }
                  #endregion
      
              #endregion
      
          }
          #endregion
      
      }
      

      我不确定您需要调整大小,请根据您的情况进行调整。

      如果你想要的话:

      Nuget:DataJuggler.Win.Controls

      来源:https://github.com/DataJuggler/DataJuggler.Win.Controls

      【讨论】:

        【解决方案3】:

        完整的工作代码: 感谢您的帮助

        using System;
        using System.Collections.Generic;
        using System.Drawing;
        using System.Linq;
        using System.Reflection;
        using System.Runtime.InteropServices;
        using System.Text;
        using System.Threading.Tasks;
        using System.Windows.Forms;
        
        namespace Move_Resize_Controls
        {
            class MyPanel: Panel
            {
        
        
                // For Moving Panel "Drag the Titlebar and move the panel"
                public const int WM_NCLBUTTONDOWN = 0xA1;
                public const int HT_CAPTION = 0x2;
        
                [DllImportAttribute("user32.dll")]
                public static extern int SendMessage(IntPtr hWnd,
                                 int Msg, int wParam, int lParam);
                [DllImportAttribute("user32.dll")]
                public static extern bool ReleaseCapture();
        
        
        
        
        
                // Constructor
                public MyPanel()
                {
        
                    typeof(MyPanel).InvokeMember("DoubleBuffered", BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, this, new object[] { true }); // Double buffer MyPanel
                    TitleBar(); // TitleBar
                    this.MinimumSize = new System.Drawing.Size(200, 200);
                }
        
        
        
        
        
        
                // Resize function for the panel - "Resizable Panel"
                protected override CreateParams CreateParams
                {
                    get
                    {
                        var cp = base.CreateParams;
                        cp.Style |= (int)0x00040000L;  // Turn on WS_BORDER + WS_THICKFRAME
                        //cp.Style |= (int)0x00C00000L;  // Move
                        return cp;
        
                    }
                }
        
        
        
        
        
        
        
                // The Title Bar
                private void TitleBar()
                {
                    Panel titleBar = new Panel();
                    titleBar.BackColor = Color.Black;
                    titleBar.Size = new Size(this.Size.Width, 20);
                    titleBar.Dock = DockStyle.Top;
                    this.Controls.Add(titleBar);
        
                    titleBar.MouseDown  += new System.Windows.Forms.MouseEventHandler(this.MouseDownTitleBar); // Mouse Down - Event
                    typeof(Panel).InvokeMember("DoubleBuffered", BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, titleBar, new object[] { true }); // Double Buffered 
        
                }
        
        
        
        
        
        
        
        
                // Move Panel
                private void MouseDownTitleBar(object sender, MouseEventArgs e)
                {
                    if (e.Button == MouseButtons.Left)
                    {
                        ReleaseCapture();
                        SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
                    }
                }
        
        
        
        
        
        
             // Make the Minumum Size - Work
                public const int WM_GETMINMAXINFO = 0x24;
        
                public struct POINTAPI
                {
                    public Int32 X;
                    public Int32 Y;
                }
        
        
                public struct MINMAXINFO
                {
                    public POINTAPI ptReserved;
                    public POINTAPI ptMaxSize;
                    public POINTAPI ptMaxPosition;
                    public POINTAPI ptMinTrackSize;
                    public POINTAPI ptMaxTrackSize;
                }
        
        
                protected override void WndProc(ref Message m)
                {
                    switch (m.Msg)
                    {
                        case WM_GETMINMAXINFO:
                            MINMAXINFO mmi = (MINMAXINFO)System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, typeof(MINMAXINFO));
                            mmi.ptMinTrackSize.X = this.MinimumSize.Width;
                            mmi.ptMinTrackSize.Y = this.MinimumSize.Height;
                            System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, m.LParam, true);
                            break;
                    }
                    base.WndProc(ref m);
                }
        
        
        
        
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-22
          • 1970-01-01
          • 2012-06-04
          • 2012-03-03
          相关资源
          最近更新 更多