如何使用 "CreateParams" 设置自定义控件的最小尺寸
How to set minimum Size of Custom Control with "CreateParams"
我正在尝试制作一个可拖动、可调整大小且最小尺寸的面板。我已将 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);
}
}
}
}
只需设置 MinimumSize 属性:
这里的 class 是我的 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
将 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);
}
}
完整的工作代码:
感谢您的帮助
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);
}
}
}
我正在尝试制作一个可拖动、可调整大小且最小尺寸的面板。我已将 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);
}
}
}
}
只需设置 MinimumSize 属性:
这里的 class 是我的 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
将 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);
}
}
完整的工作代码: 感谢您的帮助
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);
}
}
}