限制可调整大小的面板(比率和最小/最大尺寸)

时间:2017-05-02 14:18:17

标签: c# winforms panel aspect-ratio resizable

我目前正在尝试将可调整大小的面板添加到我的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的宽高比。

  3. 我如何使用上面的代码获得?有没有办法做到这一点?

1 个答案:

答案 0 :(得分: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&#34;并且重写OnResize是&#34; Windows Forms&#39;方式&#34;