2010-11-15 45 views
13

Solía ​​haber 3 puntos en la barra divisora ​​de un SplitContainer. Al igual que hay tres líneas en el cuadro de texto de detalles de pregunta en StackOverflow que muestra que se puede capturar. ¿Cómo puedo hacer esto con la barra divisora ​​de un SplitContainer en .NET?Cómo agregar agarradera en Splitter of SplitContainer

Respuesta

40

No es que tenga nada en contra de la respuesta de Alex, pero pensé que me gustaría compartir esta solución, ya que se ve un poco más agradable para mí (en una máquina XP de todos modos?).

private void SplitContainer_Paint(object sender, PaintEventArgs e) 
{ 
    var control = sender as SplitContainer; 
    //paint the three dots' 
    Point[] points = new Point[3]; 
    var w = control.Width; 
    var h = control.Height; 
    var d = control.SplitterDistance; 
    var sW = control.SplitterWidth; 

    //calculate the position of the points' 
    if (control.Orientation == Orientation.Horizontal) 
    { 
     points[0] = new Point((w/2), d + (sW/2)); 
     points[1] = new Point(points[0].X - 10, points[0].Y); 
     points[2] = new Point(points[0].X + 10, points[0].Y); 
    } 
    else 
    { 
     points[0] = new Point(d + (sW/2), (h/2)); 
     points[1] = new Point(points[0].X, points[0].Y - 10); 
     points[2] = new Point(points[0].X, points[0].Y + 10); 
    } 

    foreach (Point p in points) 
    { 
     p.Offset(-2, -2); 
     e.Graphics.FillEllipse(SystemBrushes.ControlDark, 
      new Rectangle(p, new Size(3, 3))); 

     p.Offset(1, 1); 
     e.Graphics.FillEllipse(SystemBrushes.ControlLight, 
      new Rectangle(p, new Size(3, 3))); 
    } 
} 

Espero que esto le agrade a alguien? Haa!

+0

Por ahora no estoy haciendo un nuevo divisor como sugirió alex, usando onPaint se ve mejor. La baja reputación es una mierda – SMUsamaShah

+0

Guau, no esperaba que esto fuera a ser un accesorio, ¡pero de nada! – shousper

+0

La variable 'pointRect' nunca se usa. – JYelton

11

Eso no está implementado. Si desea esa función, es mejor que obtenga el SplitContainer y anule el método OnPaint.


Actualización 1

Aquí hay algo de código para hacer lo que solicitó. Está en VB.NET y la colocación de puntos puede hacer algunos ajustes. En general, el código funciona como se esperaba.

Imports System.Windows.Forms 
Imports System.ComponentModel 
Imports System.Drawing 

Public Class SplitContainerEx 
    Inherits SplitContainer 

    ''' <summary>Determines the thickness of the splitter.</summary> 
    <DefaultValue(GetType(Integer), "5"), Description("Determines the thickness of the splitter.")> _ 
      Public Overridable Shadows Property SplitterWidth() As Integer 
     Get 
      Return MyBase.SplitterWidth 
     End Get 
     Set(ByVal value As Integer) 
      If value < 5 Then value = 5 

      MyBase.SplitterWidth = value 
     End Set 
    End Property 

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) 
     MyBase.OnPaint(e) 
     'paint the three dots 
     Dim points(2) As Point 
     Dim pointRect = Rectangle.Empty 

     'calculate the position of the points 
     If Orientation = Windows.Forms.Orientation.Horizontal Then 
      points(0) = New Point((MyBase.Width \ 2), SplitterDistance + (SplitterWidth \ 2)) 
      points(1) = New Point(points(0).X - 10, points(0).Y) 
      points(2) = New Point(points(2).X + 10, points(0).Y) 
      pointRect = New Rectangle(points(1).X - 2, points(1).Y - 2, 25, 5) 
     Else 
      points(0) = New Point(SplitterDistance + (SplitterWidth \ 2), (MyBase.Height \ 2)) 
      points(1) = New Point(points(0).X, points(0).Y - 10) 
      points(2) = New Point(points(0).X, points(0).Y + 10) 
      pointRect = New Rectangle(points(1).X - 2, points(1).Y - 2, 5, 25) 
     End If 

     e.Graphics.FillRectangle(Brushes.Gray, pointRect) 

     For Each p In points 
      p.Offset(-1, -1) 
      e.Graphics.FillEllipse(Brushes.Black, New Rectangle(p, New Size(3, 3))) 
     Next 
    End Sub 
End Class 

Actualización 2

Estoy poniendo el equivalente C# porque se ha insertado en cuestión de modo.
Si vb makes you sick, aprende a dirigirte a Convert VB.NET to C# - Developer Fusion y realiza la conversión de VB a C#.

using System; 
using System.Diagnostics; 
using System.Windows.Forms; 
using System.ComponentModel; 
using System.Drawing; 

public class SplitContainerEx : SplitContainer 
{ 

    /// <summary>Determines the thickness of the splitter.</summary> 
    [DefaultValue(typeof(int), "5"), Description("Determines the thickness of the splitter.")] 
    public virtual new int SplitterWidth { 
     get { return base.SplitterWidth; } 
     set { 
      if (value < 5) 
       value = 5; 

      base.SplitterWidth = value; 
     } 
    } 

    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     //paint the three dots 
     Point[] points = new Point[3]; 
     Rectangle pointRect = Rectangle.Empty; 

     //calculate the position of the points 
     if (Orientation == System.Windows.Forms.Orientation.Horizontal) { 
      points[0] = new Point((int)(base.Width/2), SplitterDistance + (int)(SplitterWidth/2)); 
      points[1] = new Point(points[0].X - 10, points[0].Y); 
      points[2] = new Point(points[2].X + 10, points[0].Y); 
      pointRect = new Rectangle(points[1].X - 2, points[1].Y - 2, 25, 5); 
     } else { 
      points[0] = new Point(SplitterDistance + (int)(SplitterWidth/2), (int)(base.Height/2)); 
      points[1] = new Point(points[0].X, points[0].Y - 10); 
      points[2] = new Point(points[0].X, points[0].Y + 10); 
      pointRect = new Rectangle(points[1].X - 2, points[1].Y - 2, 5, 25); 
     } 

     e.Graphics.FillRectangle(Brushes.Gray, pointRect); 

     foreach (Point p in points) { 
      p.Offset(-1, -1); 
      e.Graphics.FillEllipse(Brushes.Black, new Rectangle(p, new Size(3, 3))); 
     } 
    } 
} 
+0

¿Puede usted por favor, agregue el código anterior como c también #, VB me enferma – SMUsamaShah

+0

Gracias para agregar el código C#. – SMUsamaShah

+0

Esto funciona bien, gracias. – DarrenMB

6

Lo más cerca que se puede llegar sin pintar usted mismo es cambiar el BorderStyle a Fixed3D. Eso le dará una especie de "barra" entre los dos paneles.

Si no le gusta el aspecto hundido de los dos paneles, puede "esconder" los bordes externos colocando su panel divisor dentro de otro panel y configurando su Location en un valor negativo (por ej. -n,-n) y su tamaño a su tamaño de panel principal + 2*n. Luego, configuré Anchor en Top | Left | Bottom | Right para que se mantenga de esa manera a medida que cambia el tamaño del panel principal.

Es una especie de chapuza, pero algo ciertamente he considerado hacer que odie que no hay ninguna indicación de que el "punto de agarrar" es.

+0

Fixed3D me parece bien ... – MAW74656

2

Lo que prefiero es simplemente agregar un controlador de pintura. Esto significa que no necesita derivar una nueva clase y que la función estática se puede reutilizar fácilmente si la coloca en un archivo que puede ser compartido por varios proyectos; simplemente recuerde usar "agregar como enlace" para que, si edita el archivo, se cambiará para todos los proyectos que lo incluyan. La falla principal con esto es que no maneja automáticamente el cambio del color del control.

... 
mySplitContainer.Paint += CustomPaint.PaintSplitterWithHandle; 
... 

public static class CustomPaint { 
    public static void PaintSplitterWithHandle(object sender, PaintEventArgs p) { 
    SplitContainer splitter = sender as SplitContainer; 
    if (splitter == null) return; 
    if (splitter.Orientation == Orientation.Horizontal) 
     p.Graphics.DrawLine(Pens.DarkGray, 
      0, splitter.SplitterDistance + (splitter.SplitterWidth/2), 
      splitter.Width, splitter.SplitterDistance + (splitter.SplitterWidth/2)); 
    else 
     p.Graphics.DrawLine(Pens.DarkGray, 
      splitter.SplitterDistance + (splitter.SplitterWidth/2), 0, 
      splitter.SplitterDistance + (splitter.SplitterWidth/2), splitter.Height); 
    } 
} 
2

Realmente no quería hacer todo el trabajo sucio de dibujar un asidero cuando estaba escribiendo una herramienta de administración de la casa y que era un exceso.Como por this article on MSDN puede subclase el SplitContainer, reemplazar el método OnPaint (PaintEventArgs) e incluyen la línea siguiente:

ControlPaint.DrawGrabHandle(e.Graphics, SplitterRectangle, true, Enabled); 

Esto trazar una línea divisoria básica entre los cristales.

+0

¡Gracias! minimizó el código – SMUsamaShah

5

Me gustaron las respuestas de shousper y Alex, pero parecían un poco "complejas" para mi gusto; parecía haber más código que hubiera considerado necesario.

La respuesta de Shaun también funciona (también encontré esa en MSDN), pero en la aplicación en la que estoy trabajando, los "asideros" se volvieron bastante molestos, ya que casi llenan el divisor, y tenemos bastantes de ellos.

Así que se me ocurrió esto, que está en el medio. Sin arreglos, sin rectángulos nuevos. Tomaría muy poco trabajo adicional para el efecto '3D' de la respuesta 'aceptado', pero los 3 puntos de civil trabajaron para mí:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
{ 
    base.OnPaint(e); 

    Point centerPoint = new Point(SplitterRectangle.Left - 1 + SplitterRectangle.Width/2, SplitterRectangle.Top - 1 + SplitterRectangle.Height/2); 

    e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X, centerPoint.Y, 3, 3); 
    if (Orientation == System.Windows.Forms.Orientation.Horizontal) { 
     e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X - 10, centerPoint.Y, 3, 3); 
     e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X + 10, centerPoint.Y, 3, 3); 
    } else { 
     e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X, centerPoint.Y - 10, 3, 3); 
     e.Graphics.FillEllipse(SystemBrushes.ControlText, centerPoint.X, centerPoint.Y + 10, 3, 3); 
    } 
}