Especial Docking

Incluir un "split" para cambiar el tamaño de los controles

O cómo dividir un formulario en dos partes y poder cambiar el tamaño en ejecución

 

Publicado el  25/Ene/2004
Revisión del 22/Sep/2004

Rev. 22/Sep/04: Un pequeño bug 

 

 


En este ejemplo, veremos cómo dividir un formulario en dos partes y poder cambiar el tamaño de las mismas en tiempo de ejecución (Split).

Como te comentaba en el ejemplo de cómo incluir un formulario dentro de un control Picture...

Normalmente tendremos un formulario principal, el cual puede tener un menú principal y también en la parte superior un ToolBar. Por otro lado, en la parte inferior también tendremos un StatusBar. En el centro, (en la parte principal del formulario), tendremos dos "paneles", uno a la izquierda y otro a la derecha. En el panel izquierdo podríamos insertar un control al estilo del Outlook con una serie de botones de opciones, etc. y en el panel derecho podríamos tener el contenido de otro formulario de nuestra aplicación.

Todo esto son "deseos", ya que en el ejemplo que te voy a mostrar, todos estos "posibles" controles serán del tipo PictureBox, aunque realmente el único que "debería" ser un PictureBox es el panel de la derecha, el que contendrá el "otro" formulario. Pero, para no complicar demasiado el ejemplo, he preferido dejarlos todos como controles Picture. Sigue las "recomendaciones" de los comentarios del ejemplo y verás que te resultará fácil usar otros controles.

En este ejemplo no vamos a "incrustar" ningún formulario en el picture de la derecha, ya que la forma de hacerlo te la he mostrado en ese otro artículo, aunque al final encontrarás el código de un ejemplo completo en el que se pondrá en práctica lo explicado en aquél artículo así como en este, es decir: un formulario principal que tendrá cuatro "paneles" y en uno de ellos meteremos un segundo formulario.

Pero en este ejemplo tendremos los siguientes controles:

Cuatro controles del tipo Picture, uno que estará alineado en la parte superior, otro en la parte inferior, otro en la parte izquierda y el último en la parte derecha. Estos controles se llaman picU, picD, picL y picR respectivamente, aunque en el formulario se usarán otros nombres, simplemente para facilitar el poder usar otros controles de otros tipos y no tener que cambiar "todo" el código.
También tenemos un control Image y otro Picture que serán los que harán de barra divisoria (split). Los dos controles que se usarán para la barra divisoria se llaman: imgSplitter y picSplitter.

Lo primero que haremos es asignar a las variables definidas en el formulario los controles que tenemos en el formulario, además de ocultar el picSplitter y asignar los valores de alineación (docking) de los dos paneles del centro:

Private Sub Form_Load()
    ' asignar los controles que realmente se usarán
    ' En caso de que no sean Pictures, cambiarlos en la declaración
    Set objIzq = picL
    Set objDer = picR
    Set objSup = picT
    Set objInf = picD
    '
    ' asignar el "acoplamiento"
    objIzq.Align = vbAlignLeft
    objDer.Align = vbAlignRight
    '
    picSplitter.Visible = False
    '
End Sub

Para poder hacer que se pueda cambiar el tamaño, necesitamos que alguno de los controles se entere de que estamos moviendo la barra de desplazamiento, además de que debemos mostrar gráficamente que estamos "moviendo" dicha barra de desplazamiento. Esto último lo haremos en los eventos MosuseDown, MouseUp y MouseMove del control imgSplitter.

Private Sub imgSplitter_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
    With imgSplitter
        picSplitter.Move .Left, .Top, .Width \ 3, .Height - 20
    End With
    picSplitter.Visible = True
    moviendo = True
End Sub

Private Sub imgSplitter_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    Dim sglPos As Single
    '
    If moviendo Then
        sglPos = x + imgSplitter.Left
        If sglPos < splitLimit Then
            picSplitter.Left = splitLimit
        ElseIf sglPos > Me.Width - splitLimit Then
            picSplitter.Left = Me.Width - splitLimit
        Else
            picSplitter.Left = sglPos
        End If
    End If
End Sub

Private Sub imgSplitter_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
    sizeControls picSplitter.Left
    picSplitter.Visible = False
    moviendo = False
End Sub

Por otro lado cuando el control de la izquierda "recibe" un control, si ese control es el imgSplitter tendremos que ajustar los tamaños dependiendo de la nueva posición de dicho control. Veamos el código para aclarar este punto.

Private Sub picL_DragDrop(Source As Control, x As Single, y As Single)
    If Source = imgSplitter Then
        sizeControls x
    End If
End Sub

Y este es el código del procedimiento que se encarga de ajustar el tamaño y posición de los controles.

' Este procedimiento se usará para ajustar los tamaños de los paneles
Private Sub sizeControls(ByVal x As Long)
    Dim tMinWidth As Long
    '
    On Error Resume Next
    '
    ' el ancho mínimo que tendrá cada panel
    tMinWidth = Screen.TwipsPerPixelY * 90
    '
    ' asignar el ancho
    If x < tMinWidth Then x = tMinWidth
    If x > (Me.Width - tMinWidth) Then x = Me.Width - tMinWidth
    objIzq.Width = x
    imgSplitter.Left = x
    objDer.Left = x + 90
    objDer.Width = Me.ScaleWidth - (objIzq.Width + imgSplitter.Width)
    '
    ' asignar la parte superior
    ' aquí se puede usar otro control para saber dónde situar la parte superior
    objIzq.Top = objSup.Top + objSup.Height
    objDer.Top = objIzq.Top
    '
    ' asignar la altura
    ' aquí se puede usar otro control para saber dónde situar la parte inferior
    If objInf.Visible Then
        objIzq.Height = Me.ScaleHeight - (objSup.Top + objSup.Height + objInf.Height)
    Else
        objIzq.Height = Me.ScaleHeight - (objSup.Top + objSup.Height)
    End If
    '
    objDer.Height = objIzq.Height
    imgSplitter.Top = objIzq.Top
    imgSplitter.Height = objIzq.Height
End Sub

Aquí tienes unas capturas de la aplicación en ejecución:


El formulario antes de hacer nada...


Moviendo la barra para cambiar el tamaño.


El formulario con el nuevo tamaño de los paneles.

Aquí tienes el código con el formulario de ejemplo: dockVB6Split.zip 2.86 KB

Si quieres ver funcionando este ejemplo y el de incluir un formulario dentro de un control Picture, puedes bajarte el código completo, en el que se incluye un ejemplo de cómo poner cualquier ventana (de la que sabemos el caption o título) en un picture: DockSplitVB6.zip 5.92 KB


El formulario con el Notepad dentro de un picture.

¡Que lo disfrutes!

Nos vemos.
Guillermo


Rev. 22/Sep/04: Un pequeño bug

Reportado por Adolfo Pereiro el 1 de Agosto: (pego parte del mensaje con el bug y la solución)

Al grano, el caso es que en tu código si minimizas la ventana, hayas puesto como hayas puesto el separador de los dos PictureBox centrales, (picL, picR), al restaurar, el separador aparece en la posición mas a la izquierda posible. Espero haberme explicado bien. Yo lo he resuelto almacenando en la propiedad Tag del formulario (podría haber usado una variable global) la propiedad Left del objeto imgSplitter:

Me.Tag = imgSplitter.Left

Esto lo hago en dos eventos, en el load del form1, y en el MouseUp del imgSplitter. Posteriormente en el evento Resize del form1, asigno el valor almacenado en el Tag a la propiedad Left del imgSplitter:

imgSplitter.Left = Me.Tag

De esta manera queda solucionado el problema.

 


ir al índice