2017-05-02 174 views
0

我正在尝试向我的C#winforms项目添加可调整大小的面板。限制可调整大小的面板(比例和最小/最大大小)

我目前使用此代码来获得我想要的东西:

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

class ResizablePanel : Panel 
{ 
    private const int grab = 16; 

    public ResizablePanel() 
    { 
     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) 
     { 
      var pos = this.PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16)); 

      if (pos.X >= this.ClientSize.Width - grab && pos.Y >= this.ClientSize.Height - grab) 
       m.Result = new IntPtr(17); 
     } 
    } 
} 

其工作正常,但现在我想限制一些东西。

  1. 我不希望面板小于420x236。 我试图设置MinimumSize,但忽略了当我尝试调整大小。

  2. 我想保持宽高比为16:9。

我如何得到上面的代码?有没有办法做到这一点?

+0

你有没有试过SetBoundsCore()?这是一种虚拟方法,您可以在像您这样的情况下使用它。 – Bahrom

回答

1

处理从this answer采用的WM_SIZING消息。

if (m.Msg == 0x84) 
{ 
    var pos = this.PointToClient(new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16)); 

    if (pos.X >= this.ClientSize.Width - grab && pos.Y >= this.ClientSize.Height - grab) 
    m.Result = new IntPtr(17); 
} 
else if (m.Msg == 0x216 || m.Msg == 0x214) 
{ 
    // WM_MOVING || WM_SIZING 
    // Keep the aspect and minimum size 
    RECT rc = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); 
    int w = rc.Right - rc.Left; 
    int h = rc.Bottom - rc.Top; 
    w = w > 420 ? w : 420; 
    rc.Bottom = rc.Top + (int)(w * 9.0/16); 
    rc.Right = rc.Left + w; 
    Marshal.StructureToPtr(rc, m.LParam, false); 
    m.Result = (IntPtr)1; 
    return; 
} 

的RECT结构被定义为

[StructLayout(LayoutKind.Sequential)] 
public struct RECT { 
    public int Left; 
    public int Top; 
    public int Right; 
    public int Bottom; 
} 

我还试图重写OnResize事件,这是更简单的,但是,调整大小当面板闪烁。

protected override void OnResize(EventArgs eventargs) 
{ 
    base.OnResize(eventargs); 
    if (this.Width < 420) 
     this.Size = new Size(420, 236); 
    else 
     this.Size = new Size(this.Width, (int)(this.Width * 9.0/16)); 
} 

两种方法其实都是一样的东西,处理消息队列更低水平“的Win32状”和压倒一切的onResize受到的“Windows窗体的方式”。

+0

所以我尝试了OnResize版本和它的工作正常。我通过使用DoubleBuffered和重写CreateParams修复了闪烁问题。即使OnResize工作,我仍然想测试你的想法的第一个版本,但我不明白如何/在哪里使用它。我对所有这些东西都很陌生,至今仍在学习,你能否给我一个关于在哪里以及如何使用它的小教程? – Backslash

+0

哦,我看到我还需要根据表格的大小限制最大高度/宽度,因为如果拉伸得太大,您无法抓住角落,使其变小。 :D – Backslash

+0

只需将代码复制到WndProc方法中,我只需在if后添加一个else。 – kennyzx