Autor
|
Tema: Matriz de controles MenuStrip partiendo modo diseño (VBasic 2013) (Solucionado) (Leído 5,250 veces)
|
Tazmania40
Desconectado
Mensajes: 42
|
Buenos días, veo que en VB6 teníamos la propiedad Index y cuando creabamos una matriz de controles te preguntaba si ponías el mismo nombre VB "Desea crear una matriz de controles...?", asi cuando empleabas el mismo evento Click solo hacía referencia al pulsado por la propiedad Index. Eso es lo que preciso en mi programa, tengo un menú bastante extenso y ya cambiado muchas cosas y solo tengo 2 submenus que hacen referencia según lo que pulsas a un mismo código, repito por tanto un total de 20, este código. Private Sub MnuRepasoSuma1_Click(sender As Object, e As EventArgs) Handles MnuRepasoSuma1.Click Form2.Close() TAB = "SUMAR" : RE = 1 Form2.Show() End Sub Private Sub MnuRepasoSuma2_Click(sender As Object, e As EventArgs) Handles MnuRepasoSuma2.Click Form2.Close() TAB = "SUMAR" : RE = 2 Form2.Show() End Sub Private Sub MnuRepasoSuma3_Click(sender As Object, e As EventArgs) Handles MnuRepasoSuma3.Click Form2.Close() TAB = "SUMAR" : RE = 3 Form2.Show() End Sub ... ...
Y así 20 veces, requiero por tanto algo parecido a la matriz, pero claro no voy a crear todo el MenuStrip por código porque es muy extenso, con muchas propiedades, colores, checked, font... y tardo mucho más y quería saber si se puede agrupar un mismo evento de pulsaciones de Click, como antes se hacía con Index para aprovechar un mismo codigo y que sólo cambio una variable que es RE que según lo pulsado antes se podía jugar con esa variable Index en VB6. Requiero hacer lo mismo pero en VB2013, haber si hay alguna forma sin la de crear todo el menú con los submenus porque sino lo dejo asi (copiar y pegar) aunque no lo veo bien. Por eso me imagino que debe existir alguna forma de agrupar eventos y que se sepa cuando pulsas el 1, el 2, el 3 y que todo vaya a un mismo evento Click. Muchas gracias y como siempre seguiré mirando a ver si veo alguna solución.
|
|
« Última modificación: 14 Octubre 2015, 11:56 am por Tazmania40 »
|
En línea
|
|
|
|
Lekim
Desconectado
Mensajes: 268
|
Hola Básicamente una manera es esta y lo puedes poner en un evento o función: Public Class Form1 Dim LabelArray(6) As Label Private sub Evento() For Index As Integer = 0 To LabelArray.Length - 1 LabelArray(Index) = New Label Me.Controls.Add(LabelArray(Index)) Next End Sub End Class
Ahora querrás que estén en un lugar u otro. Entonces debes modificar las propiedades. Además seguramente necesites usar eventos como Click o MouseEnter. Aquí te dejo un ejemplo: Option Explicit On Option Strict On Public Class Form1 Dim LabelArray(6) As Label Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim StartLabel As Point = New Point(10, 10) For Index As Integer = 0 To LabelArray.Length - 1 LabelArray(Index) = New Label() With LabelArray(Index) .Text = "Label" & Index .ForeColor = Color.Red .Font = New Font("Arial", 10) .BackColor = Color.Blue .TextAlign = ContentAlignment.MiddleCenter .Location = New Point(StartLabel.X, StartLabel.Y) End With Me.Controls.Add(LabelArray(Index)) 'Añade el control al Form StartLabel.Y += 30 'Incrementa la posición Y, para que los labels queden uno debajo del otro Next 'Vincula LabelArray_Click con el evento Click del control LabelArray For I As Integer = 0 To LabelArray.Length - 1 AddHandler LabelArray(I).Click, AddressOf LabelArray_Click Next End Sub Private Sub LabelArray_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 'Obtiene el índice del control seleccionado Dim Index As Integer = Array.IndexOf(LabelArray, sender) If Index.Equals(0) Then LabelArray(0).Text = "HOLA" End Sub End Class
Añado que esto es en WindowsForms, en WPF, es algo diferente. Ahora, lo paso a WPF
Aquí está lo mismo pero para WPF. Option Explicit On Option Strict On Class MainWindow Dim LabelArray(6) As Label Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded Dim StartLabel As New Point(X:=50, Y:=50) For Index As Integer = 0 To LabelArray.Length - 1 LabelArray(Index) = New Label() With LabelArray(Index) .Content = "Label" & Index 'Texto que muestra el Label .Width = 100 .Height = 20 .Foreground = Brushes.Red 'Color del texto .Background = Brushes.Blue 'Color del fondo .FontFamily = New FontFamily("Arial") .FontSize = 15 .Padding = New Thickness(25, 1, 0, 0) 'Colocación del texto dentro del label .VerticalAlignment = Windows.VerticalAlignment.Top 'Colocación del label .HorizontalAlignment = Windows.HorizontalAlignment.Left 'Colocación del label .Margin = New Thickness(StartLabel.X, StartLabel.Y, 0, 0) 'Margen Izquierda, Arriba, Derecha, Abajo End With Grid1.Children.Add(LabelArray(Index)) 'Añade el control a Grid1 (NOTA: El Grid debe ser nombrado para poder establecer esta propiedad) StartLabel.Y += 30 Next For I As Integer = 0 To LabelArray.Length - 1 AddHandler LabelArray(I).MouseLeftButtonDown, AddressOf LabelArray_MouseLeftButtonDown 'Vincula LabelArray con el evento LabelArray_Click y evento Click Next End Sub Private Sub LabelArray_MouseLeftButtonDown(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Dim Index As Integer = Array.IndexOf(LabelArray, sender) If Index.Equals(0) Then LabelArray(0).Content = CStr("Hola") End Sub End Class
Por cierto, por si no lo sabes hay un foro para VB.NET, como supongo que sabrás esto es para Visual Basic X http://foro.elhacker.net/net-b62.0/
|
|
« Última modificación: 6 Octubre 2015, 23:55 pm por Lekim »
|
En línea
|
|
|
|
Lekim
Desconectado
Mensajes: 268
|
Mis disculpas porque realmente no leí detenidamente tu pregunta Vale, te refieres al MenuStrip. Y mira que está bien claro. Bueno, parece ser que no se puede hacer tal y como se hace por ejemplo con un Label, como he mostrado en el ejemplo. Puedes hacer esto: Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim idMenu = "1001" Dim Menu1 As New ToolStripMenuItem("Menu Item") Menu1.DropDownItems.Add("Item_1") Menu1.DropDownItems.Add("Item_2") MenuStrip1.Items.Add(Menu1) 'Agrega el menú 'crea eventos para Menu1 AddHandler Menu1.DropDownItemClicked, AddressOf Menu1_click End Sub Private Sub Menu1_click(ByVal sender As Object, ByVal e As ToolStripItemClickedEventArgs) If e.ClickedItem.Text = "Item_1" Then Me.Text = "Item_1" If e.ClickedItem.Text = "Item_2" Then Me.Text = "Item_2" End Sub End Class
Si prefieres trabajar con índices, se me ocurre hacer lo siguiente para el evento Click: Private Sub Menu1_click(ByVal sender As Object, ByVal e As ToolStripItemClickedEventArgs) Dim IndexItem As Integer Select Case e.ClickedItem.Text Case "Item_1" : IndexItem = 0 Case "Item_2" : IndexItem = 1 End Select If IndexItem = 0 Then Me.Text = "Item1" If IndexItem = 1 Then Me.Text = "Item2" End Sub
|
|
« Última modificación: 7 Octubre 2015, 13:59 pm por Lekim »
|
En línea
|
|
|
|
Tazmania40
Desconectado
Mensajes: 42
|
Gracias Lekim, lo primero desconocía que hubiera un subforo para .net en Programación general, a partir de ahora expongo mis preguntas ahí. De momento solo programo con Windows Form, lo adapté todo para trabajar con Windows Form, incluso la apariencia porque ya de por sí es difícil pasar de VB6 a Visual Basic 2013, como para ponerse a programar con WPF, más bonito con web, gráficos... pero prefiero lo que ya sabía y adaptarlo, además en los programas utilizo la versión .Net Framework 3.5 para que tenga compatibilidad con XP porque tengo compañeros que utilizan todavía ese SO. Estoy probando tu código del Label, cambiándolo por un botón y desconocía como agregar eventos a una matriz de controles. AddHandler LabelArray(I).Click, AddressOf LabelArray_Click
y el cómo llamar a ese evento Click o naturalmente el que pongas añadiendo a AddHandler y comparándolo con una variable como antes se hacía con Index. Private Sub LabelArray_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 'Obtiene el índice del control seleccionado Dim Index As Integer = Array.IndexOf(LabelArray, sender) If Index.Equals(0) Then LabelArray(0).Text = "HOLA" End Sub
A todo esto se me ocurre añadir una clase o módulo, de forma que las matrices de controles no tengan definido el número de array "Dim LabelArray() As Label" y luego dimensionarlas desde el programa principal "LabelArray = New Label (NumTotal - 1) {}" donde pongamos en la variable "NumTotal" el número de elementos que vayamos a utilizar. Veo que hay que ir haciendo procedimientos para ahorrarnos código que antes con dos pulsaciones podíamos hacer. Voy a probar para mi programa añadiendo los elementos ToolStripMenuItem por código, seguramente genere un procedimento dentro del Formulario principal y más adelante ya crearé un módulo para ir acoplando distintos Controles de arrays y así intentar en mis programas que la utilización sea parecida como antes con VB6 e index. MUCHAS GRACIAS, si me surge algún problema contestaré por aqui; pero lo dicho las nuevas preguntas lo haré por el foro NET.
|
|
|
En línea
|
|
|
|
Tazmania40
Desconectado
Mensajes: 42
|
Pongo el código que ya he probado y funciona el evento Click, he cambiado algunas cosas puesto que primero el control MenuStrip lo creo en tiempo de diseño, tengo muchos menús ya creados y submenús y ponerlo todo en código es más lioso. Solo pongo en código los 3 submenus que tienen varias opciones y que desembocan todos en un mismo click donde solo cambio una variable RE. Private Prueba(2) As ToolStripMenuItem 'Declaro Array de elementos 'Pongo los elementos en el submenú correspondiente y los agrego, además del evento Click Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Prueba(0) = New ToolStripMenuItem("Numero1") Prueba(1) = New ToolStripMenuItem("Numero2") Prueba(2) = New ToolStripMenuItem("Numero3") For I = 0 To 2 MnuRepasoSuma.DropDownItems.Add(Prueba(I)) AddHandler Prueba(I).Click, AddressOf EventoMenu Next I End Sub Private Sub EventoMenu(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim Index As Integer = Array.IndexOf(Prueba, sender) 'Obtiene índice control seleccionado Form2.Close() TAB = "SUMAR" : RE = Index + 1 Form2.Show() End Sub
Naturalmente tendre que utilizar for..next para añadir propiedades restantes, como dije seguramente genere una Clase con el procedimiento de declarar array y añadir propiedades y controles. Una última pregunta, aunque funciona bien hay que utilizar el método Dispose, he leido algo que es como el Unload Me, pero no se muy bien como codificarlo y si al emplear algún Procedimiento hay que liberar objeto y en el código que tengo donde habría que colocarlo o bien al ser un código simple no hace falta y ya se libera todo cuando se cierra el programa? Gracias y salu2
|
|
|
En línea
|
|
|
|
Lekim
Desconectado
Mensajes: 268
|
Hola Tazmania40 Está genial tu código. Muy buen aporte. Había visto ejemplos por ahí que usaban DropDownItems para crear los items con índices, pero los códigos estaba incompletos y no me funcionaban. Igualmente en tu código no has puesto la variable MnuRepasoSuma de clase ToolStripMenuItem al que hace referencia aquí: MnuRepasoSuma.DropDownItems.Add(Prueba(I))
Además, ¿Qué ocurre si quiero añadir un separador. Esas líneas que hay en los menús para separar conceptos. ¿Cómo hago para crear submenus en los Items? También he despejado esa duda. Experimentando un poco he conseguido hacerlo. He hecho este código a partir del que has facilitado para despejar esas dudas y que cualquiera puede hacer un copia y pega y probarlo, usarlo o mejorarlo. Option Strict On Option Explicit On Public Class Form1 Private mnuStrip1 As New MenuStrip() Private mainToolStripMenuItem As New ToolStripMenuItem() Private Item(3) As ToolStripMenuItem Private SubItem1(3) As ToolStripMenuItem Private Separator(0) As ToolStripSeparator Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load '*****Crea la cabezera del menú mnuStrip1 ******** Me.mainToolStripMenuItem.Text = "Archivo" mnuStrip1.Items.AddRange(New ToolStripItem() {mainToolStripMenuItem}) 'Añade un submenú para añadir Items Me.Controls.Add(mnuStrip1) '************************************************** ' For numItms As Integer = 0 To Item.Count - 1 Dim name As String = Nothing Select Case numItms Case 0 : name = "Abrir" Case 1 : name = "Guardar" Case 2 : name = "Recientes" Case 3 : name = "Cerrar" 'Crea un Separador encima del Item3 Separator(0) = New ToolStripSeparator mainToolStripMenuItem.DropDownItems.Add(Separator(0)) 'Separador End Select Item(numItms) = New ToolStripMenuItem(name) mainToolStripMenuItem.DropDownItems.Add(Item(numItms)) 'Añade subItems al Item 2 If numItms = 2 Then 'Añade subItems al Item 2 (Recientes) For numSubItm As Integer = 0 To SubItem1.Count - 1 Select Case numSubItm Case 0 : name = "File1" Case 1 : name = "File2" Case 2 : name = "File3" Case 3 : name = "File4" End Select SubItem1(numSubItm) = New ToolStripMenuItem(name) 'Crea SubItem1 para Item2 Item(2).DropDownItems.Add(SubItem1(numSubItm)) 'Añade 'SubItem1 Next End If Next 'Crea evento click para los Items For I As Integer = 0 To Item.Count - 1 AddHandler Item(I).Click, AddressOf Item_Click Next I 'Crea evento click para los Subitems For I As Integer = 0 To SubItem1.Count - 1 AddHandler SubItem1(I).Click, AddressOf SubItem1_Click Next I End Sub Private Sub Item_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 'Obtiene el índice del Item seleccionado Dim Index As Integer = Array.IndexOf(Item, sender) 'Muestra un mensaje con el texto del Item MessageBox.Show(Item(Index).Text) 'Cierra la apliación si se hace click en el Item 3 de la colección If Index = 3 Then End End Sub Private Sub SubItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 'Obtiene el índice del Item seleccionado Dim Index As Integer = Array.IndexOf(SubItem1, sender) 'Muestra un mensaje con el texto del SubItem MessageBox.Show(SubItem1(Index).Text) End Sub End Class
Como ves el menú 'Archivo' se crea en tiempo de ejecución. No hace falta añadir controles al formulario. Mediante "mnuStrip1.Items.AddRange(New ToolStripItem() {mainToolStripMenuItem})" se crea el menú para los Items y finalmente creamos el menú completo (sin subitems) mediante "Controls.Add(mnuStrip1)". Depués hago lo que has hecho tú y añado el "submenu" con sus Items y su índice correspondiente, pero esta vez añadiendo un separador. La posición de cada menú dependerá del lugar que ocupe la línea de código en que se crea, como muetra el ejemplo. Hoy mismo he conseguido hacer lo propio con un menú emergente. Supón que quieres hacer un menú emergente (contextMenu o PopupMenu en VB6) dentro de un control y quieres crear items con sus índices y crear además separadores y subítems para los items. Aquí dejo el código de ejemplo: CREAR UN MENÚ EMERGENTE (contextmenu) DENTRO DE UN CONTROL -Inserta un ListBox en el form. Este ejemplo usa el evento ListBox1_MouseDown para mostrar el menú cuando se pulsa el botón derecho del ratónOption Explicit On Option Strict On Public Class Form1 Dim Contextmenu1 As New ContextMenu() Dim ContextItems1(3) As MenuItem Dim SubItems1(3) As MenuItem Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load For numCItm As Integer = 0 To ContextItems1.Count - 1 Dim name As String = Nothing Select Case numCItm Case 0 : name = "Item0" Case 1 : name = "-" Case 2 : name = "Item2" Case 3 : name = "Item3" End Select ContextItems1(numCItm) = New MenuItem(name) If numCItm = 2 Then For numCSubItm As Integer = 0 To SubItems1.Count - 1 Select Case numCSubItm Case 0 : name = "SubItem0" Case 1 : name = "SubItem1" Case 2 : name = "SubItem2" Case 3 : name = "SubItem3" End Select 'Añade SubItems al Item 2 SubItems1(numCSubItm) = New MenuItem(name) 'Crea SubItemX del Item2 ContextItems1(numCItm).MenuItems.Add(SubItems1(numCSubItm)) 'Añade el subItemX 'Evento para los SubItems AddHandler ContextItems1(numCItm).MenuItems(numCSubItm).Click, AddressOf SubItems1_Click Next End If 'Añade los Items Contextmenu1.MenuItems.Add(ContextItems1(numCItm)) 'Evento de los Items AddHandler ContextItems1(numCItm).Click, AddressOf ContextItems1_Click Next End Sub Private Sub ContextItems1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 'Obtiene índice control seleccionado Dim Index As Integer = Array.IndexOf(ContextItems1, sender) 'Muestra el texto del Item en la barra de título MessageBox.Show(ContextItems1(Index).Text) End Sub Private Sub SubItems1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 'Obtiene índice control seleccionado Dim Index As Integer = Array.IndexOf(SubItems1, sender) 'Muestra el texto del SubItems en la barra de título MessageBox.Show(SubItems1(Index).Text) End Sub Private Sub ListBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox1.MouseDown If e.Button = MouseButtons.Right Then Contextmenu1.Show(ListBox1, New System.Drawing.Point(e.Location.X, e.Location.Y)) End If End Sub End Class
|
|
« Última modificación: 11 Octubre 2015, 23:53 pm por Lekim »
|
En línea
|
|
|
|
Tazmania40
Desconectado
Mensajes: 42
|
Muy bueno tu código Lekin, he probado lo del separador, no se me había ocurrido puesto que como te comente el control MenuStrip lo cree en modo diseño y sólo la parte que me hacía falta por código, por eso "MnuRepasoSuma" procede de un nombre del MenuStrip (diseño). Si tuviera que programarlo por código todo sería muy extenso porque cambio propiedades de name, font, checked, pongo imágenes de iconos... y creo que eso sería mejor hacerlo en una clase o un módulo que no se muy bien para hacer una array de controles que se utilice para cuando necesitemos llamarlo como antes se hacía con VB6.
Como mencioné solo faltaría aplicar el método Dispose, he leido algo pero veo que no me hace falta aplicarlo porque los objetos los empleo en el Formulario principal y estos se liberan en el archivo "Form1.Designer.vb" al finalizar el Form. Aunque no se si al salir debería llamar al Objeto.Dispose() para liberar por si acaso el GC (Garbage Collector) no los libera bien los recursos.
Si empleara alguna clase o módulo donde genere los objetos veo que si hay que implementar el método Dispose, que la verdad sería otro tema a tratar y extenso, donde las explicaciones de Microsoft las veo muy complicadas de entender y tendría que ponerme a ello, cosa que de momento para mi programa no necsito.
Excelente tus aportaciones y con el menú contextual. Este Visual Basic se parece cada vez más a Visual C, no tengo nada en contra pero para mi pienso que todo lo que se pueda realizar por diseño te ahorras trabajo y si hay que emplear mucho código es mejor crearte tus clases o módulos para no ser repetitivo por tanto no debería haber desaparecido la forma antigua de llamar a los array de controles y eso debería haberse implementado en Visual Basic 2013.
Muchas gracias por todo y mis nuevas preguntas iran al foro net
|
|
« Última modificación: 14 Octubre 2015, 11:59 am por Tazmania40 »
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Lista de Controles ActiveX para Visual Basic 6.0
Programación Visual Basic
|
--<<<@u6u$t0>>>--
|
8
|
29,982
|
15 Octubre 2005, 20:32 pm
por -sagitari-
|
|
|
Controles ActiveX para Visual Basic 6 del tipo Windows XP
Programación Visual Basic
|
marrion
|
1
|
1,482
|
15 Enero 2008, 14:47 pm
por Tughack
|
|
|
Obtencion de Inicio de Sesion Windows en Visual basic 2013
Programación Visual Basic
|
jcc2014
|
1
|
2,010
|
23 Junio 2014, 03:33 am
por MCKSys Argentina
|
|
|
Estoy perdido... Visual Basic 2013
Programación Visual Basic
|
old.dude
|
2
|
2,046
|
5 Julio 2014, 15:17 pm
por old.dude
|
|
|
Crear matriz partiendo de un vector ingresado
Programación C/C++
|
Faceless
|
7
|
3,190
|
5 Octubre 2016, 23:41 pm
por Faceless
|
|