¿Como se hace un menú DE IMÁGENES colapsables?

Iniciado por Eleкtro, 21 Febrero 2013, 22:57 PM

0 Miembros y 2 Visitantes están viendo este tema.

Eleкtro

La idea que tengo es que al pulsar sobre el botón (1), se muestre una imagen (y otros controles que quiero usar) manteniendo la relación de aspecto entre el resto de elementos (2)

¿Debe haber algún control para hacer este tipo de diseño, no?

¿Como se puede hacer de una manera sencilla? (es decir, sin tener que posicionar los elementos todo el rato en el form con "control.location"...)








EDITO: Esto es lo más parecido que he encontrado, pero aparte de que no se adapta a lo que necesito (porque usa títulos, no imágenes) está escrito en C# y el VS ni me lo compila para que pueda aprender algo...
http://www.codeproject.com/Articles/53318/C-Custom-Control-Featuring-a-Collapsible-Panel

EDITO 2: Esta forma de hacerlo es la que quiero EVITAR, porque con varios elementos es un completo lío tener que estar resizando cada elemento:

[youtube=640,360]http://www.youtube.com/watch?v=Y5fijH11EiE[/youtube]








_katze_

esto es lo mas cercano a lo que necesitas, yo tenia mi version modificada y demas pero no la encuentro ya que esta se descontinuo.
http://www.vbforums.com/showthread.php?576403-Expandable-GroupBox

Eleкtro

nada _katze_ he estado probando pero ese control tampoco me sirve, al final lo he hecho manuálmente pero necesito ayuda para automatizar la taréa.






El tema es que necesito hacer un menú colapsable (no me sirve ningún control de terceros colapsables para hacer esto porque es un menú por imágenes y paneles)

Os dejo unas imagenes para que entendais lo que quiero hacer...

Yo esto se hacerlo de forma manual, es decir, en el evento "click" de un botón, al clickarlo, expandir manualmente el panel, osea redimensionar más colocarlo (control.size + control.location) y hacer lo mismo con todo el resto de elementos...

Pero esa manera es un verdadero fiasco porque tengo más de 60 elementos y necesito encontrar una forma dinámica de que todo se organize de un modo más automático, pero no llego a la solución ni a la conclusión de como se podría hacer esto, ni siquiera en pseudocódigo, nada, mi cabeza y mi creatividad no dán para más, jeje.

PD: en las imagenes los "elementos" son botones, pero en el code original son PictureBoxes, y lo verde serían paneles.

Ah, por cierto, el problema más grande creo que es que los "elementos" (los paneles) no pueden tener el mismo tamaño, algunos son más grandes que otros y esto no puedo cambiarlo de ninguna manera, por eso no he llegado a una solución matemática (que tampoco soy un génio) ni he podido sacar conclusiones en pseudocode. De otra forma creo que sería muy fácil, si todos los paneles fuesen del mismo tamaño sólo tendría que "handlear" todos los elementos en un sub, hacer una regla de trés con todos los elementos y restarle/sumarle el valor del tamaño del panel para resizarlos... en fín me valdría de ese valor para poder hacer todo de una forma más automática, pero es que no puedo hacerlo así.














Ari Slash

Pues primero que nada te recomendaria crear los controles de forma dinamica, y con un correlativo y formato definido, luego a cada "boton" creado le enlazas un evento comun en el cual, tome el nombre del objeto (sender) y recorra todos los siguientes moviendo su posicion, extrayendo el correlativo del mismo nombre.

Si dejas cada fila de controles en un panel, debes solo reubicar ese panel, ya que los objetos internos a ese panel se reubican de acuerdo al panel.

Te dejo una funcion que hice hace mucho, a lo mejor se puede optimizar mas, en esta funcion tengo un check (tipo boton) que me desplega un richtext.

Espero que te sirva, saludos.

Código (csharp) [Seleccionar]

private void moverPaneles(object sender, EventArgs e)
        {
            int extender = this.altura_rich + 10;
            int aspecto = int.Parse(((CheckBox)sender).Name.Replace("obsbtn", ""));
            GroupBox grupo = (GroupBox)((Panel)((CheckBox)sender).Parent).Parent;
            int n_grupo = int.Parse(grupo.Name.Replace("Grupo",""));
            bool fin = false;

            if (((CheckBox)sender).Checked)
            {
                grupo.Height += extender;
                ((Panel)grupo.Controls.Find("Panel" + aspecto, true)[0]).Height += extender;

                Panel panel;
                aspecto++;
                for (int i = aspecto; i <= this.total_aspectos; i++)
                {
                    try
                    {
                        panel = (Panel)grupo.Controls.Find("Panel" + i, true)[0];
                        panel.Location = new Point(panel.Location.X, panel.Location.Y + extender);
                    }
                    catch (Exception ex)
                    {
                        fin = true;
                        break;
                    }
                }

                if (fin)
                {
                    n_grupo++;
                    for (int i = n_grupo; i <= this.total_grupos; i++)
                    {
                        try
                        {
                            grupo = (GroupBox)aspectosPanel.Controls.Find("Grupo" + i, true)[0];
                            grupo.Location = new Point(grupo.Location.X, grupo.Location.Y + extender);
                        }
                        catch (Exception ex)
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                grupo.Height -= extender;
                ((Panel)grupo.Controls.Find("Panel" + aspecto, true)[0]).Height -= extender;

                Panel panel;
                aspecto++;
                for (int i = aspecto; i <= this.total_aspectos; i++)
                {
                    try
                    {
                        panel = (Panel)grupo.Controls.Find("Panel" + i, true)[0];
                        panel.Location = new Point(panel.Location.X, panel.Location.Y - extender);
                    }
                    catch (Exception ex)
                    {
                        fin = true;
                        break;
                    }
                }

                if (fin)
                {
                    n_grupo++;
                    for (int i = n_grupo; i <= this.total_grupos; i++)
                    {
                        try
                        {
                            grupo = (GroupBox)aspectosPanel.Controls.Find("Grupo" + i, true)[0];
                            grupo.Location = new Point(grupo.Location.X, grupo.Location.Y - extender);
                        }
                        catch (Exception ex)
                        {
                            break;
                        }
                    }
                }
            }

        }

Eleкtro

#4
Cita de: Ari Slash en  4 Marzo 2013, 16:50 PM
Pues primero que nada te recomendaria crear los controles de forma dinamica, y con un correlativo y formato definido

luego a cada "boton" creado le enlazas un evento comun en el cual, tome el nombre del objeto (sender) y recorra todos los siguientes moviendo su posicion, extrayendo el correlativo del mismo nombre.

Muchas gracias por el code, de C# sólo entiendo un poco la sintaxis, tendré que pasarlo a VBNET a ver si saco algo en claro.

Lo de handlear todos los controles a un sub e interactuar con ellos mediante el sender se hacerlo, pero... ¿Como hago lo de mover sus posiciones sin saber las dimensiones exactas de cada elemento desplegable?, eso es lo que me reconcome la cabeza... y sé que se puede hacer, pero no tengo mucha capacidad resolutiva con este tipo de problemas que son más matemáticos que otra cosa xD.

Por cierto, lo que he subrayado de tu comentario, ¿me lo podrías explicar mejor?, creo que no lo he entendido ¿Crear controles de forma dinámica, correlativos y con formato definido?, no he entendido nada de esa parte, ¿Que me estás sugeriendo que haga?, ¿Donde busco información acerca de eso?.

Un saludo!








Ari Slash

Bueno para saber las dimensiones solo llamas al objeto a traves de controls, y extraes su dimension. Usando Controls debes saber solo el nombre del objeto para tener acceso a sus propiedades,
algo asi (no tengo visual studio en este momento) esto es ficticio:

(imagen)((Panel)miform.Controls.find("panel1")).controls.find("imagen1").altura

por eso te digo que crees los controles con formato, me refiero a que por ejemplo la primera parte es un boton y una imagen dentro del panel,
entonces como son los primeros deberas llamarlos Panel1, imagen1, boton1, eso es un formato definido de nombres para los objetos.
Y de forma dinamica bueno no creo que sea necesario, me refiero a traves de un ciclo for crear los objetos y ubicarlos en tu formulario (todo por codigo) sin usar el diseñador, pero esto viendolo bien no es necesario.

Saludos

Eleкtro

#6
uf... a ver, esto es lo que llevo intentando.

Quiero repetir que esto se hacerlo manuálmente, pero es un coñazo, y lo que pretendo es automatizarlo bastante, como por ejemplo especificando sólamente el tamaño del elemento a expandir, y esto es lo que he intentado en el siguiente code que voy a mostrar

Esto es un form con 4 botones y 4 paneles del mismo tamaño de Ancho, los paneles están detrás de los botones:



Todos los controles siguen este orden de nombre numérico:
Panel_X
Button_X


Bien, y esto es mi frustrado intento, he conseguido que funcione corréctamente el primer elemento ("Button_1"), es decir, que se expanda manteniendo la relación entre los otros elementos:





Pero si intento expandir otro elemento que no séa el "1", esto se convierte en un cáos:



Además, luego está el tema de revertir los cambios, es decir, si expando el elemento "1", y luego quiero expandir el "3", primero tengo que contraer el elemento que estaba abierto, el "1", para luego expandir el "3"... digo yo.


En fín, el código:
Código (vbnet) [Seleccionar]
Public Class Form1

   Dim Selected_TAB As Integer ' El número del botón clickado
   Dim Margin_TAB As Integer = 30 ' el margen de espacio que le quiero dar a los botones
   Dim Element_Size_Y As Integer ' la altura del panel

   Private Sub sub_btn_sel(sender As Object, e As EventArgs) Handles Button_1.Click, Button_2.Click, Button_3.Click, Button_4.Click

       Selected_TAB = sender.name.split("_")(1)  ' El número del botón clickado
       Dim Temp_Margin_TAB As Integer = Margin_TAB

       ' Estas son las dimensiones de altura de cada panel que quiero expandir/contraer
       Select Case Selected_TAB
           Case 1
               Element_Size_Y = 25
           Case 2
               Element_Size_Y = 50
           Case 3
               Element_Size_Y = 80
           Case 4
               Element_Size_Y = 155
           Case Else
       End Select

       For Each Control In Panela.Controls
           If Control.GetType.ToString.Contains("Button") Then
               Dim Botoncito As Button = CType(Control, Button)
               If Not Botoncito.Name = "Button_" & Selected_TAB Then
                   Margin_TAB += Temp_Margin_TAB
                   Botoncito.Location = New Point(Botoncito.Location.X, Element_Size_Y + Margin_TAB)
               End If
           End If
       Next

       For Each Control In Panela.Controls
           If Control.GetType.ToString.Contains("Panel") Then
               Dim Panelito As Panel = CType(Control, Panel)
               If Not Panelito.Name = "Panel_" & Selected_TAB Then
                   Panelito.Visible = False
               Else
                   Panelito.Visible = True
                   Panelito.Size = New Size(Panelito.Width, Element_Size_Y)
                   Panelito.Location = New Point(Panelito.Location.X, Temp_Margin_TAB)
               End If
           End If
       Next
   End Sub

End Class