2017-05-02 233 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