|
|
A menudo las aplicaciones que requieren seleccionar un dispositivo antes de efectuar algún tipo de comunicacion, no ofrecen ninguna información adicional sobre el estado del dispositivo. Sobre todo si hablamos del puerto serie, normalmente nos ofrecen una simple enumeración de los COM. Esto último es el causante de que la aplicación nos permita seleccionar un puerto que en ocasiones no existe o está siendo usado por otro programa. Os propongo una idea con la intención de mejorar y facilitar la selección de este tipo de dispositivos en nuestras aplicaciones. Básicamente se trata de enumerar en un ‘ComboBox’ personalizado los puertos existentes en nuestro equipo, utilizando el mandato : My.Computer.Ports.SerialPortNames.ToArray
En el momento de la inicialización del ‘combobox’ asignaremos el evento de ‘DrawItem’ a la función que enriquecerá el aspecto, añadiendo al nombre un rectángulo coloreado y el texto correspondiente a la disponibilidad del puerto. AddHandler ComboBox1.DrawItem, AddressOf cmbo_SerialPorts_Status
No dudéis en contactar conmigo si necesitáis aclarar o necesitáis entender alguna parte del código.
Para poder darle mayor difusión los comentarios del código están en inglés, aunque si os parece oportuno y necesario puedo posteároslo también en español.
|
Sometimes our communications applications are required to select any type of external device, and normally these applications are not giving any extra information about their availability. This is the case when talk around serial ports, normally when select the port only have a simple enumeration of COM’s, this may be confusing at time leaving at users selecting inexistent ports or ports that simply are already in use. With this sample, you can improve and make easy these device selections in our applications.
The main think is enumerate serial port inside our customized ‘ComboBox’, using : My.Computer.Ports.SerialPortNames.ToArray
After when initialize our combo only need assign ‘DrawItem’ event to function with our personalized combo draw, AddHandler ComboBox1.DrawItem, AddressOf cmbo_SerialPorts_Status
This function are adding red rectangle and “busy” text when no have availability, and green rectangle and “available” text when the port is free.
Please no doubt in contact with me if you need any other explanation or opinion about this.
|
|
|
Public Class Form1
‘Enumerate Serial Ports on Machine
‘Get Serial Port availability
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
‘Just drag & drop combobox from toolbox to form designer
Me.ComboBox1.DrawMode = DrawMode.OwnerDrawVariable ‘select my own drag mode
Me.ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList ‘aspect when drop down
Me.ComboBox1.DataSource = My.Computer.Ports.SerialPortNames.ToArray ‘enumerate serialports
Me.ComboBox1.TabIndex = 0 ‘select first tabindex
AddHandler ComboBox1.DrawItem, AddressOf cmbo_SerialPorts_Status ‘draw my personal cmbo
End Sub
‘
‘ Draw our custom combo
Private Sub cmbo_SerialPorts_Status( _
ByVal sender As Object, _
ByVal CmboItem As System.Windows.Forms.DrawItemEventArgs)
‘ Draw the background of the item.
CmboItem.DrawBackground()
‘
‘Default Values if port is available
Dim status As String = «Available»
Dim brush As New SolidBrush(Color.Green)
Dim font As System.Drawing.Font = Me.Font
Dim fontbrush As Brush = Brushes.Black
Dim rectangle As Rectangle = New _
Rectangle(2, CmboItem.Bounds.Top + 2, _
CmboItem.Bounds.Height, _
CmboItem.Bounds.Height – 4)
‘
‘Check for port availability
Try
‘ If port open & close with no exception
‘ draw the item with default font and green rectangle
Dim PortTest As New System.IO.Ports.SerialPort
PortTest = My.Computer.Ports.OpenSerialPort(My.Computer.Ports.SerialPortNames(CmboItem.Index))
PortTest.Close()
Catch ex As Exception
‘ If port is not available
‘ draw the item with italic & strikeout font and red rectangle
brush = New SolidBrush(Color.Red)
status = «In Use»
font = New Font(FontFamily.GenericSansSerif, Me.Font.Size, FontStyle.Italic Xor FontStyle.Strikeout)
fontbrush = Brushes.DimGray
End Try
‘fill combo item rectangle
CmboItem.Graphics.FillRectangle(brush, rectangle)
‘write text with actual port status for this item
CmboItem.Graphics.DrawString( _
My.Computer.Ports.SerialPortNames(CmboItem.Index) + » – « + status, _
font, _
fontbrush, _
New _
RectangleF(CmboItem.Bounds.X + rectangle.Width, _
CmboItem.Bounds.Y, _
CmboItem.Bounds.Width, _
CmboItem.Bounds.Height) _
)
‘ Draw focus rectangle when mouse are over an item.
CmboItem.DrawFocusRectangle()
End Sub
End Class
Hola Pep, es realmente útil saber si el puerto esta disponible. Un ejemplo muy interesante. Gracias.
Offtopic: por cierto, continua activo el grupo SpainNet? He intentado acceder a la web pero no esta disponible. Saludos!
Hola Ivan!!
Pues ciertamente es util y sobretodo facilita la seleccion de los puertos a los usuarios que no quieren entrar en la administracion de dispositivos para saber si existe el com o no.
Tambien como sabes el puerto puede no tener ningun dispositivo fisicamente enchufado, pero quizas este ocupado por alguna otra aplicacion 🙂
En tanto a SpainNet, por supuesto que sigue vivo y coleando, lo que ocurre es que nos quedamos sin servidor propio. Aunque puedes seguir nuestras actividades en :
http://www.codezone.com/UserGroupInformation.CodezoneCom?ActiveID=3498
Saludos y gracias por el interes.
Gracias por responder. Ya miraré la información de Codezone. Lo preguntaba porque te recuerdo de asistir a alguna conferencia en la UVIC. 😉
Saludos!
Hola,
Muy interesante!!! pero estoy intentado pasarlo a c# y tengo algunos problemas con la transformación… podrías ponerlo en c# también?
Moltes gràcies…
mtz
Hola Mtz…
Podrias indicarme la parte donde tienes problemas para pasarlo a C#… puedes contactar conmigo a traves de [Contact] en la parte superior derecha del Blog.
Espero tus noticias,
Pep Lluis,
HOLA PEPELLUIS QUIERO HACER ALGO PARECIDO PERO NO TENGO DISPONIBLE LO DEL
My.Computer.Ports.SerialPortNames.ToArray
ES QUE YO TENGO .NET Y NO ESTA O NECESITO IMPORTAR HERRAMIENTAS EXTRAS
Hola Mariano,
En principio ‘My’ esta disponible en Visual Studio como espacio de nombres, la unica duda es saber si estas utilizando VB y quizas la version ‘Express’.
De todas formas dispones de la expresion :
Dim EnumeracionPuertos As New ComboBox
EnumeracionPuertos.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames.ToArray)
Si estas utilizando C#, puedes leerte este post:
http://msmvps.com/blogs/peplluis/archive/2009/03/16/como-enumerar-los-com-s-de-nuestro-equipo-en-vb-y-en-c.aspx
Saludos,
Pep Lluis,
Amigo Pep Lluis, necesito rediccionar un puerto serie, pues al ejecutar un programa antiguo msdos me dice «El sistema no puede abrir el puerto com3 requerido por la aplicación»… lo cierto, es que me da la opción cerrar ó omitir, si lo omito en realidad funciona bien, pero con el com1 que es el que tengo habilitado (he probado cambiar en windows com3, y ahora me dice que no puede conectar con el com1 ¡vaya lio!), ¿que tengo que hacer, ¿podrias ayudarme? Te lo agradezco muchisimo…. ma_emilio@hotmail.com gracias
Hola Emilio,
Puedes contactar conmigo a traves de la opcion [Contac] en la parte superior izquierda de esta pagina.
Lo que necesitaria saber es como estas utilizando tu aplicacion en MSDOS o Windows… y en todo caso, porque MSDOS y Windows?
Espero tus noticias,
Pep Lluis,
Saludos.
Felicidades por esta aportacion, es bastante buena. Quiero recalcar que este tipo de aportaciones nos sacan de apuros a muchos novatillos.
Solo tengo una pregunta: Existe alguna forma de modificar el codigo para saber no solamente si esta en uso el puerto sino tambien que aplicacion lo esta utilizando??
De antemano gracias por tomarse el tiempo de contestar. Buen dia.
Jorge!
Pues la verdad… es una pregunta muy buena e interesante, lo cierto es que desde ‘management’ puedes inventariar el hardware, pero desconozco de que lugar del sistema puedes extraer la lista de quien tiene cedidos los recursos.
Lo tendre en mente y si localizo como hacerlo lo compartire con todos vosotros, de otra forma si averiguas tambien me gustara saberlo.
Gracias por la pregunta.
Saludos,
Pep Lluis,
Pep; a qué se debe que al compilar el código me arroja un error en:
New _
RectangleF(CmboItem.Bounds.X + rectangle.Width, _
CmboItem.Bounds.Y, _
CmboItem.Bounds.Width, _
CmboItem.Bounds.Height) _
)
Me dice que el índice está fuera de intervalo; salu2
Hola Javier,
Mira de ejecutar la instruccion completa en una sola linea (Sin bajo guiones)
CmboItem.Graphics.DrawString(My.Computer.Ports.SerialPortNames(CmboItem.Index) + » – » + status, font, fontbrush, New RectangleF(CmboItem.Bounds.X + rectangle.Width,CmboItem.Bounds.Y, CmboItem.Bounds.Width, CmboItem.Bounds.Height))
Espero que asi funcione,
Pep Lluis,
Hola Pep, estaba viendo tu ejemplo y me parece interesante. Pero fijate que también me tira el mismo error que a Javier, y veo q el problema no está en poner o no en una sola línea el código q le sugeriste a él. Dime algo, que tamaño (Height y Width) le has definido al ComboBox1?
Hola Douglas,
Para provar este ejemplo, es necesario crear un nuevo proyecto «windows forms» añadir un Combobox desde el cuadro de herramientas, copiar y pegar el codigo de este ejemplo y listo.
Esta verificado usando visual Studio 2008… recuerda que debeis arrastrar y soltar el combobox al form de vuestra aplicacion, puede que sea ese el detalle.
Si aun asi no os funciona comunicate conmigo a traves de [contact] y te mando el proyecto en .zip.
Saludos,
Pep Lluis,
Hola de nuevo Pep,
Gracias por responder tan rápido. Fíjate que encontré el problema, y era que yo lo estaba probando en Visual Studio 2005 y está hecho para que corra perfectamente como tú lo dijiste en 2008. El único cambio que le hice fue que en la línea Me.ComboBox1.DataSource = My.Computer.Ports.SerialPortNames.ToArray que es la que llena el combo, le quité el ToArray y listo!!
Te lo informo para que lo sepas y por si algún otro visita tu página que me imagino que seguro lo harán y tiene la misma dificultad, pues que conozca la solución!!!
Saludos,
Gracias Douglas por compartir la Info,
Saludos,
Pep Lluis,
Muy buen dia, gusto de saludarte, muy interesante este ejemplo, solo con un favor, como puedo saber la descripcion del dispositivo que esta en el puerto. gracias
Hola Mario,
Los puertos serie no pueden enumerar los dispositivos conectados a ellos. Solo en caso de conocer de antemano que tipo de disposivo esta conectado, nuestra aplicacion puede interrogarlo para saber cosas sobre el. A nivel de protocolo no existen descriptores genericos.
Saludos,
PepLluis,
Excelente tu espiritu solidario y el dseo de compartir con otros tu conocmieto.
Realmente eso hace creser mas a un a las personas d bien.
Gracias de antemano.
Conoces si existe la forma de que en ves d que apareca COM1, Com2 …. Aparezca el nombre que sale en el administrador de dispositivos ?
en el listado de los puertos… alg asi como, puerto de comunicaciones xxxxx,, con el objetivo de que cuando insertemos un cable usb a Rs32 aparezca el Nombre del Cable y as conocer con mas presicion cual es el puerto qeu estaremos utilizando.
Hola buena noche.
Esta es la cuarta ves qeu te escribo buscando a misma situacón, pero nunca he podido ver una respuesta, ni en el foro nien el correo.
Posiblemente no lo he estado haciendo correctamente pero lo voy a intentar otra ves mas.
¿Enumerar los puertos con el api del Setupapi.dll para obtener el nombre descriptivo d lospuertos como aparecen en el Administrador de dispositivos.?
Hola Nico,
Lamento que no encuentres la respuesta, pero respondi a Mario con la misma pregunta mas arriba, como bien sabes el los foros son el sitio adecuado para plantear preguntas i obtener respuestas pues existen un monton de expertos atentos a responder las preguntas sobre cada tema. Lamento no poder ayudarte con el api Setupapi.dll pues no esta en el rango de mi experiencia. Te animos a que lo vuelvas a intentar en los foros.
Gracias por tu compresion,
PepLluis,
Es posible hace lo mismo pero , web (VB) , yo contrui el codigo , pero al ponerlo en un servidor WEB , claramente me dice que el puerto no esta ya que el dispositovo lo tento conectado en mi PC y no en el servidor WEb.
Alguna idea ?
Saludos.