Come ridimensionare i controlli separati da uno splitter oltre le dimensioni del pannello del contenitore?

StackOverflow https://stackoverflow.com/questions/1817453

  •  08-07-2019
  •  | 
  •  

Domanda

Ho alcuni UserControls su un pannello separato da splitter. Il pannello contenente è impostato su AutoScroll.

Poiché il controllo Splitter prende in considerazione le dimensioni del suo genitore quando ridimensiona i controlli che "divide", il ridimensionamento dei controlli utente al suo interno è limitato dalle dimensioni del pannello.

Voglio essere in grado di spostare lo splitter verso il basso ovunque si trovasse il mouse (anche oltre i limiti del contenitore / modulo) quando l'utente lo rilascia e fare ridimensionare il pannello del contenitore di conseguenza (e mostrare le barre di scorrimento se necessario) .

Ho provato tutti i tipi di combinazioni avvolgendolo con pannelli diversi, giocando con MinSize ecc. Questo è il migliore che mi è venuto in mente finora, ma non è quello che voglio:

alt text

Qualcuno ha qualche idea?

È stato utile?

Soluzione

Puoi impostare un gancio per mouse quando il pulsante del mouse viene premuto e sganciato quando viene rilasciato il pulsante del mouse. Nel callback hook, puoi guardare la posizione del mouse e ridimensionare il controllo come appropriato.

Modifica:

È possibile invece utilizzare un controllo speciale che l'utente può trascinare per mantenere la posizione di scorrimento nell'angolo in basso a destra del contenitore padre. L'utente può trascinare il controllo per ingrandire l'area e, se non si utilizzano le impostazioni di ancoraggio o dock, è possibile regolare manualmente la dimensione dei controlli per riempire l'area principale.

Ho implementato qualcosa del genere qualche tempo fa per un progetto che ho realizzato. L'ho reso triangolare e sembra simile al "grip". su un ToolStrip . Ecco alcuni frammenti di codice dal controllo ScrollHolder :

public ScrollHolder()
{
    this.Size = new Size(21, 21);
    this.BackColor = SystemColors.Control;
}

protected override void OnPaint(PaintEventArgs e)
{
    Point bottomLeft = new Point(0, this.Height);
    Point topRight = new Point(this.Width, 0);
    Pen controlDark = SystemPens.ControlDark;
    Pen controlLightLight = SystemPens.ControlLightLight;
    Pen controlDark2Px = new Pen(SystemColors.ControlDark, 2);
    Point bottomRight = new Point(this.Width, this.Height);
    e.Graphics.DrawLine(
        controlLightLight, 
        bottomLeft.X, 
        bottomLeft.Y - 2, 
        bottomRight.X, 
        bottomRight.Y - 2);
    e.Graphics.DrawLine(controlDark, bottomLeft, topRight);
    e.Graphics.DrawLine(
        controlLightLight, 
        bottomLeft.X + 1, 
        bottomLeft.Y, 
        topRight.X, 
        topRight.Y + 1);
    e.Graphics.DrawLine(controlDark2Px, bottomLeft, bottomRight);
    e.Graphics.DrawLine(controlDark2Px, bottomRight, topRight);
    int xNumberOfGripDots = this.Width / 4;
    for (int x = 1; x < xNumberOfGripDots; x++)
    {
        for (int y = 1; y < 5 - x; y++)
        {
            DrawGripDot(e.Graphics, new Point(
                this.Width - (y * 4), this.Height - (x * 4) - 1));
        }
    }
}

private static void DrawGripDot(Graphics g, Point location)
{
    g.FillRectangle(
        SystemBrushes.ControlLightLight, location.X + 1, location.Y + 1, 2, 2);
    g.FillRectangle(SystemBrushes.ControlDark, location.X, location.Y, 2, 2);
}

protected override void OnResize(EventArgs e)
{
    this.SetRegion();
    base.OnResize(e);
}

private void SetRegion()
{
    GraphicsPath path = new GraphicsPath();
    path.AddPolygon(new Point[] 
    { 
        new Point(this.Width, 0), 
        new Point(this.Width, this.Height),
        new Point(0, this.Height) 
    });
    this.Region = new Region(path);
}

Per quanto riguarda l'implementazione del comportamento reale, probabilmente vorrai:

  • Scorri fino al supporto per scorrimento quando viene spostato all'esterno dell'area visibile:
  • Quando scorri fino al supporto per scorrimento, rallentalo chiamando Thread.Sleep per un breve periodo (ad esempio 50 ms).

Altri suggerimenti

Devi impostare la proprietà MinExtra su Splitter su un numero negativo elevato. Mentre la proprietà stessa non lo consente, è possibile modificare il campo tramite la riflessione:

typeof(Splitter).GetField("minExtra", Reflection.BindingFlags.Instance | Reflection.BindingFlags.NonPublic).SetValue(mySplitter, -10000);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top