2017-05-02 4 views
0

J'essaie actuellement d'ajouter un panneau redimensionnable à mon projet winforms C#.Restreindre le panneau redimensionnable (ratio et taille min/max)

Actuellement, je suis en utilisant ce code pour obtenir ce que je veux:

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); 
     } 
    } 
} 

Son fonctionne bien, mais maintenant je voudrais limiter un certain nombre de choses.

  1. Je ne veux pas que le panneau soit plus petit que 420x236. J'ai essayé de définir le MinimumSize mais en ignorant cela quand j'essaye de redimensionner.

  2. Je souhaite conserver un format d'image de 16: 9.

Comment pourrais-je obtenir cela avec le code ci-dessus? Y'a-t'il un quelconque moyen d'y arriver?

+0

Avez-vous essayé SetBoundsCore()? C'est une méthode virtuelle et vous pouvez l'utiliser dans des situations comme la vôtre. – Bahrom

Répondre

1

Gérer le message WM_SIZING, adopté de this answer.

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; 
} 

Le struct rect est défini comme

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

J'ai aussi essayé evênement OnResize, ce qui est beaucoup plus simple, cependant, le panneau clignote lors de redimensionnement.

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)); 
} 

Les deux approches sont en fait la même chose, la manipulation file d'attente de messages est plus faible « comme Win32 » et OnResize est primordiale « façon Windows Forms ».

+0

J'ai donc essayé la version OnResize et son fonctionnement. J'ai corrigé le scintillement en utilisant DoubleBuffered et en remplaçant CreateParams. Même si OnResize fonctionne, je voudrais encore tester la première version de votre idée, mais je ne comprends pas comment/où l'utiliser. Je suis novice dans ce domaine et j'apprends encore, pourriez-vous me donner un petit "tutoriel" sur où et comment utiliser cela? – Backslash

+0

Oh et j'ai vu que j'aurais aussi besoin d'inclure une limite à la hauteur/largeur max basée sur la taille de la forme car si vous l'étirez trop grand vous ne pouvez pas saisir le coin pour le rendre plus petit. : D – Backslash

+0

Il suffit de copier le code dans votre méthode WndProc, je viens d'ajouter un autre si après votre if. – kennyzx