Autor Tema: Rellenar con FloodFill usando GDI+ en VB6  (Leído 108 veces)

0 Usuarios y 1 Visitante están viendo este tema.

TOLO68

  • Bytes
  • *
  • Mensajes: 31
  • Reputación: +2/-0
    • Ver Perfil
Rellenar con FloodFill usando GDI+ en VB6
« en: Febrero 16, 2017, 07:05:38 pm »
Buenas a Todos
Tengo este codigo en VB6 que crea un poligono con lineas
he probado en otro codigo tambien con lineas seguidas de arcos y demas y funciona
lo que hace es rellenar el interior del dibujo en un color

-------------------------------------------------------------------------

Private Declare Function FloodFill Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long

Sub Form_Click()

   ScaleMode = 3
   ForeColor = vbBlue
   Line (50, 50)-(300, 50)
   Line -(200, 200)
   Line -(50, 150)
   Line -(50, 50)
   FillStyle = 0
   FillColor = vbBlue
   FloodFill Form1.hdc, 53, 53, vbBlue

End Sub

-------------------------------------------------------------------------

La pregunta es si conoceis alguna manera de hacerlo en VB6 pero con GDI+ por el tema del antialias, ya que he buscado por internet y dicen que no existe el FloodFill en GDI+, algunos dicen que hay que hacerlo con una funcion usando getpixel y setpixel

Esto es porque tengo que hacer dibujos irregulares con diferentes formas, por ejemplo algo como una estrella con puntas redondeadas( las puntas serian arcos), y el resto lineas, por eso necesito lo del floodfill para primero crear el dibujo y luego rellenarlo dandole las coordenadas X,Y en el interior como lo hace en el ejemplo anterior

Muchas Gracias a Todos


LeandroA

  • Administrador
  • Petabyte
  • *****
  • Mensajes: 1063
  • Reputación: +147/-8
    • Ver Perfil
Re:Rellenar con FloodFill usando GDI+ en VB6
« Respuesta #1 en: Febrero 16, 2017, 10:25:35 pm »
yo no conosco con GDI+, pero la pregunta es si no es el usuario quien decidiria el punto donde pintar, no tiene mucho sentido, se puede hacer algo mediante el array de bits de la imagen pero despues te enfrentarias a el problema del antialias donde o se perderia o quedaria para el traste.

No sera que vos queres rellenar un polígono? si es eso es lo que puse el otro dia y ahi si lo veo mas viable.

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 50
  • Reputación: +6/-0
    • Ver Perfil
Re:Rellenar con FloodFill usando GDI+ en VB6
« Respuesta #2 en: Febrero 16, 2017, 10:47:11 pm »
Tolo68, cuando hablábamos de la transparencia (una semanas atrás), te decía que no te habías quedado con la lección importante... las máscaras.

Una vez que aprendes a crear máscaras y usar transparencias se puede hacer infinidad de cosas, con solo un poco de imaginación (y también prueba y error, por supuesto).

El caso es que dada una figura, y que la quieras rellenar de algo, se debe crear una máscara partiendo de la figura. La máscara es como un molde positivo, luego se crea el molde negativo, esto es se invierte la máscara, entonces ahora la superficie ocupada es precisamente la que quieres rellenar, entonces ahora esa superficie si necesitas pintarla, rellenarla con una brocha, etc... lo haces, y luego fundes ambas imágenes (en este caso sin transparencia (pero de igual modo es una operación ROP, de fusión))... la original con la que original modificada a máscara, invertida y coloreada/enbrochada... y todas esas operaciones se hacen con funciones que más o menos ya debes conocer en GDI+ o al menos GDI.

El uso de máscaras y transparencias, es como sumas y restas de superficies, tienes que mirarlo que es igual a las operaciones lógicas (or and, not, xor, not and, not or, not xor), con los bytes.... la unica diferencia es que es a una escala mayor, y que definen una superficie, etc.... Si aprendes a sumar, restar superficies, invertirlas, hacerlas negras y blancas, etc... habras aprendido la mitad o más delo que necesitas para dominar gráficos (la otra mitad es entender las funciones que ya existen en alguna librería o crearlas por tu propia cuenta). y... bueno, un pequeño porcentaje también es necesario para entender los píxeles, el color... que también son bytes y aplicar operaciones lógicas...

Yo no estoy muy puesto en GDI+, normalmente me basta con GDI, pero GDI+ es una vuelta más de rosca, en cuanto a calidad, velocidad y más funcionalidad...
Si entiendes el proceso, de lo que hay que hacer, es sólo cuestión de apilar las funciones que necesitas usar.... aunque no exista una función específica, aplicando varias funciones en pasos sucesivos, se consiigue la funcionalidad deseada.... de eso trata GDI, de tener 'funciones primitivas' para hacer cosas complejas partiendo de funciones más simples y archiconocidas.
« última modificación: Febrero 16, 2017, 10:53:49 pm por NEBIRE »

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 50
  • Reputación: +6/-0
    • Ver Perfil
Re:Rellenar con FloodFill usando GDI+ en VB6
« Respuesta #3 en: Febrero 16, 2017, 11:16:42 pm »
Si quieres porgramar tu mismo el allgoritmo a bajo nivel, puede interesarte una pagina como esta:
https://es.wikipedia.org/wiki/Algoritmo_de_relleno_por_difusi%C3%B3n

Nota que Flood fill, tiene muchas variaciones, la más conocida se llamaa Boundary fill, y si tiene degradado, incluso se llama Fountain Fill...

La ventaja de hacerlo manualmente, es que solo requiere una única operación, frente a las varias consecutivas trabajando con máscaras, por tanto al final tu algoritmo puede ser más rápido incluso aunque el algoritmo no esté optimizado del todo... Aún así, requiere una buena optimización...

Si quieres implementarlas por tu cuenta, he aquí un esquema del algoritmo (muy, muy sencillito):
http://web.cs.ucdavis.edu/~ma/ECS175_S00/Notes/0411_a.pdf

Aquí un enlace, que explica similar al pdf:
http://www.siggraph.org/education/materials/HyperGraph/scanline/outprims/polygn6a.htm

TOLO68

  • Bytes
  • *
  • Mensajes: 31
  • Reputación: +2/-0
    • Ver Perfil
Re:Rellenar con FloodFill usando GDI+ en VB6
« Respuesta #4 en: Febrero 17, 2017, 07:05:00 am »
Hola a todos de nuevo, gracias por las respuestas, lo que dice LEANDRO de ser el usuario que decide el punto donde pintar, eso seria para un programa de dibujo tipo paint, pero aqui lo elijo yo porque es para los controles que estoy haciendo, pero veo que has entendido lo que queria :), que seria parecido al bote de pintura del paint.

Lo de rellenar el poligono ya lo estoy usando para hacer una aguja de un Gauge, ( un circulo con relleno en el centro , y luego un triangulo fino y largo con el poligono para la aguja, y voy rotando los puntos con Sin y Cos del triangulo), a ver si os puedo hacer una captura de pantalla para que lo veais

Lo que comenta NEBIRE sobre las mascaras tambien las he usado en algunos controles como el Display hexadecimal o el Display Matrix, para poder elegir entre 16 millones de colores para el color del LED, fue lo mejor porque antes tenia solo 3 colores, los 3 bitmaps)

os dejo aqui el link de la web para que podais ver las capturas de pantalla.
http://windevelop.hol.es

La pagina esta en desarrollo pero poco a poco la voy haciendo, asi como voy acabando los controles y creando algunos nuevos, asi ya se va posicionando en GOOGLE.

El unico que puede descargarse es el DisplayHEX.

Lo de usar el algoritmo para el antialias tambien se me habia ocurrido. :)
o incluso usar Bezier para hacer curvas, que creo que si se puede rellenar igual que el poligono

En el Knob hice el circulo antialias con solo GDI32 , con un algoritmo que encontre por la red, creo que era el sistema de WU o algo asi.

La cuestion es ir buscando ideas

Bueno, gracias de nuevo por vuestra ayuda. :)

 

Virgil Tracy

  • Kilobyte
  • **
  • Mensajes: 64
  • Reputación: +38/-1
    • Ver Perfil
Re:Rellenar con FloodFill usando GDI+ en VB6
« Respuesta #5 en: Febrero 17, 2017, 02:20:53 pm »
¿ Y usando path ?  :P

Código: Visual Basic
  1. Option Explicit
  2.  
  3.  
  4. Private Declare Function CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Dest As Any, Src As Any, ByVal cb As Long) As Long
  5. Private Declare Function GdiplusStartup Lib "gdiplus" (token As Long, inputbuf As GDIPlusStartupInput, Optional ByVal outputbuf As Long = 0) As Long
  6. Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
  7. Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, graphics As Long) As Long
  8. Private Declare Function GdipSetSmoothingMode Lib "gdiplus" (ByVal graphics As Long, ByVal SmoothingMd As SmoothingMode) As Long
  9. Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal graphics As Long) As Long
  10. Private Declare Function GdipCreatePath Lib "gdiplus" (ByVal brushmode As FillMode, path As Long) As Long
  11. Private Declare Function GdipAddPathLine Lib "gdiplus" (ByVal path As Long, ByVal x1 As Single, ByVal y1 As Single, ByVal x2 As Single, ByVal y2 As Single) As Long
  12. Private Declare Function GdipFillPath Lib "gdiplus" (ByVal graphics As Long, ByVal Brush As Long, ByVal path As Long) As Long
  13. Private Declare Function GdipDrawPath Lib "gdiplus" (ByVal graphics As Long, ByVal pen As Long, ByVal path As Long) As Long
  14. Private Declare Function GdipCreateSolidFill Lib "gdiplus" (ByVal argb As Long, Brush As Long) As Long
  15. Private Declare Function GdipCreatePen1 Lib "gdiplus" (ByVal color As Long, ByVal Width As Single, ByVal unit As GpUnit, pen As Long) As Long
  16. Private Declare Function GdipDeleteBrush Lib "gdiplus" (ByVal Brush As Long) As Long
  17. Private Declare Function GdipDeletePen Lib "gdiplus" (ByVal pen As Long) As Long
  18. Private Declare Function GdipDeletePath Lib "gdiplus" (ByVal path As Long) As Long
  19.  
  20.  
  21. Private Type GDIPlusStartupInput
  22.     GdiPlusVersion                      As Long
  23.     DebugEventCallback                  As Long
  24.     SuppressBackgroundThread            As Long
  25.     SuppressExternalCodecs              As Long
  26. End Type
  27.  
  28.  
  29.  
  30. Private Enum FillMode
  31.    FillModeAlternate        ' 0
  32.   FillModeWinding          ' 1
  33. End Enum
  34.  
  35. Private Enum GpUnit  ' aka Unit
  36.   UnitWorld      ' 0 -- World coordinate (non-physical unit)
  37.   UnitDisplay    ' 1 -- Variable -- for PageTransform only
  38.   UnitPixel      ' 2 -- Each unit is one device pixel.
  39.   UnitPoint      ' 3 -- Each unit is a printer's point, or 1/72 inch.
  40.   UnitInch       ' 4 -- Each unit is 1 inch.
  41.   UnitDocument   ' 5 -- Each unit is 1/300 inch.
  42.   UnitMillimeter ' 6 -- Each unit is 1 millimeter.
  43. End Enum
  44.  
  45. ' Quality mode constants
  46. Private Enum QualityMode
  47.    QualityModeInvalid = -1
  48.    QualityModeDefault = 0
  49.    QualityModeLow = 1       ' Best performance
  50.   QualityModeHigh = 2      ' Best rendering quality
  51. End Enum
  52.  
  53. Private Enum SmoothingMode
  54.    SmoothingModeInvalid = QualityModeInvalid
  55.    SmoothingModeDefault = QualityModeDefault
  56.    SmoothingModeHighSpeed = QualityModeLow
  57.    SmoothingModeHighQuality = QualityModeHigh
  58.    SmoothingModeNone
  59.    SmoothingModeAntiAlias
  60. End Enum
  61.  
  62. Dim GdipToken As Long
  63.  
  64. Private Sub Form_Click()
  65. Dim pGraphics As Long
  66. Dim path As Long
  67. Dim crSolid As Long
  68. Dim penOutLine As Long
  69.  
  70. Call GdipCreateFromHDC(Me.hDC, pGraphics)
  71. Call GdipSetSmoothingMode(pGraphics, SmoothingModeHighQuality)
  72.  
  73. Call GdipCreatePath(FillModeAlternate, path)
  74. Call GdipAddPathLine(path, 50, 50, 300, 50)
  75. Call GdipAddPathLine(path, 300, 50, 200, 200)
  76. Call GdipAddPathLine(path, 200, 200, 50, 150)
  77. Call GdipAddPathLine(path, 50, 150, 50, 50)
  78.  
  79. Call GdipCreateSolidFill(ConvertColor(vbBlue, 100), crSolid)
  80. Call GdipCreatePen1(ConvertColor(vbBlue, 255), 0.8, UnitWorld, penOutLine)
  81.  
  82. Call GdipFillPath(pGraphics, crSolid, path)
  83. Call GdipDrawPath(pGraphics, penOutLine, path)
  84.  
  85.  
  86. Call GdipDeleteBrush(crSolid)
  87. Call GdipDeletePen(penOutLine)
  88. Call GdipDeletePath(path)
  89.  
  90. Me.Refresh
  91.  
  92. Call GdipDeleteGraphics(pGraphics)
  93.  
  94. End Sub
  95.  
  96. Private Sub Form_Load()
  97.  
  98. InitGDI
  99.  
  100. Me.ScaleMode = vbPixels
  101. Me.AutoRedraw = True
  102. Me.BackColor = vbWhite
  103.  
  104. End Sub
  105.  
  106. Private Sub Form_Unload(Cancel As Integer)
  107.  
  108. TerminateGDI
  109.  
  110. End Sub
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119. Private Function ConvertColor(color As Long, alpha As Long) As Long
  120. Dim argb(0 To 3) As Byte
  121.  
  122. argb(3) = CByte(alpha)
  123. argb(0) = ((color \ &H10000) And &HFF) 'blue
  124. argb(1) = ((color \ &H100) And &HFF) 'green
  125. argb(2) = (color And &HFF) 'red
  126. CopyMemory ConvertColor, argb(0), 4&
  127.  
  128. End Function
  129.  
  130.  
  131. 'Inicia GDI+
  132. Private Sub InitGDI()
  133.     Dim GdipStartupInput As GDIPlusStartupInput
  134.     GdipStartupInput.GdiPlusVersion = 1&
  135.     Call GdiplusStartup(GdipToken, GdipStartupInput, ByVal 0)
  136. End Sub
  137.  
  138. 'Termina GDI+
  139. Private Sub TerminateGDI()
  140.     Call GdiplusShutdown(GdipToken)
  141. End Sub
  142.  
  143.  

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 50
  • Reputación: +6/-0
    • Ver Perfil
Re:Rellenar con FloodFill usando GDI+ en VB6
« Respuesta #6 en: Febrero 22, 2017, 01:38:30 pm »
Lo que comenta NEBIRE sobre las mascaras tambien las he usado en algunos controles como el Display hexadecimal o el Display Matrix, para poder elegir entre 16 millones de colores para el color del LED, fue lo mejor porque antes tenia solo 3 colores, los 3 bitmaps)

os dejo aqui el link de la web para que podais ver las capturas de pantalla.
http://windevelop.hol.es

El unico que puede descargarse es el DisplayHEX.
mmm... al leerte, me parece entender que usas las máscaras a nivel de byte, para elegir color. Aunque es la misma esencia, aplicado a una superficie, el concepto cambia. Creo que no hablamos de lo mismo...
Una máscara de bits, sirve para permitir que determinados bits, sigan ahí, o para filtrarlos y por tanto que permanezca el resto menos esos...
Una máscara de imagen (hace lo mismo), opera sobre un array de píxeles y en esencia esa máscara contiene solo dos valores en sus píxeles: blanco (todos los bits a 1) o negro (todos los bits a cero). La imagen de máscara es luego operada pixel a píxel con otra imagen para muy diferentes efectos, desde las transparencias hasta definir regiones (añadir, excluir regiones)... con el uso de la máscara, básicamente cada píxel de ella, 'decide' si se acepta o rechaza por completo, el píxel de destino, ya que:
'1' and píxel = píxel
'0' and pixel = 0
'1' or píxel = 1
'0' or pixel = pixel
Y con solo esas 4 operaciones, pueden desde crearse máscaras, a bloquear píxeles, asignarlos, o convertirlos en blanco o negro (esto es crear otra máscara, partiendo de una imagen y otra máscara, lo que sirve para añadir o eliminar regiones, permitiendo el 'clipping' sobre regiones).

En un control tan simple, como un display LCD, no tiene mucho sentido usar máscaras (de imagen), puede dibujarse perfectamente solo con el método line. Ni siquiera hace falta recurrir a las APIs GDI, para ese control, el método Line es suficientemente rápido, como para no requerir nada más. Redibujar el control probablemente no requiera más de una diezmilésima de segundo, aunque GDI, lo redujera a la mitad o a un tercio, es imperceptible a esa escala.

------------------------------------------------------

...luego de mirar tu página y bajando ese control, me ha sorprendido  :o negativamente  :o el enorme tamaño que tiene compilado... la friolera de 204kb. y tras ponerlo en un proyecto, me  :-[ decepciona   :-[ aún más, que básicamente tiene solo  :'( 7 propiedades específicas  :'( del control: 3 para elegir el color, 1 para preselecciones de colores, Digitos, Value, SizeDisplay y la innecesaria (a mi juicio) LeftZero). Muy poca funcionalidad y opciones para 204kb.
En general lo que hace aumentar el tamaño de un control son los recursos, cuando uno añade muchas imágenes, sonidos o textos. Pero el control carece de sonido, no necesita imágenes y tampoco  :( están documentadas  :( las propiedades. :(

-------------------------------------

Se me ha ocurrido hacer un control, del mismo tipo, un Display-LCD de 7 segmentos... y bueno, le he añadido todas las propiedades que se me han ocurido, sumo hasta 18, con muchas opciones (por ejemplo el tamaño, va de 0 a 12 (no de 0-2 como en el tuyo), los digitos van de 0-255 tamaño de 1 byte, si también 0, el tuyo va de 1-32, aunque puede valer porqué limitarlo tanto, cómo sabemos que alguien no fuera a necesitar 40 caracteres. El tamaño de byte, es un límite perfecto para estos casos?
En mi caso, la cantidad de tamaños posibles junto a otra propiedad 'proporción' (que decide el valor de cuadrícula, de los dígitos para el ancho y alto (9x5, 9x6, 8x5,10x7, etc...hasta 21 distintos)) permiten un total de 13x21 = 273 combinaciones diferentes). En mi control el tamaño en realidad lo que define es el grosor del segmento... lo que hace que el tamaño final del control dependa también del valor de 'proporcion' y el número de dígitos. También añadí otra propiedad DigitoDecim, que actúa como si fueran decimales, aunque básicamente lo que permite es elegir otro color para ellos...

En fin tal como figura en la imagen que adjunto de ejemplo...


y después de compilado, solo pesa 60kb. teniendo en cuenta que si solo compilas un control en VB6, sin nada de código, tiene un tamaño de 20kb.
Se puede afirmar que el código ocupa solo 40kb. y eso que le he metido todas las propiedades que he imaginado (y media docena de eventos)... incluso una llamada 'displayTime', que al activarla a True, el control 'se convierte' en un reloj digital, que se actualiza cada segundo. Incluso una propiedad para elegir que base numérica soportar: Octal, Decimal o Hexadecimal... Caracteres como el guión bajo, medio y alto están disponibles en todos los casos.
Total, que si a tu control le quitamos esos 20 kb. se queda en 184, frente a los 40 del mío.... siento enorme curiosidad por saber que código contiene para estar inflado 4'5 veces el tamaño, con sólo la cuarta-quinta parte de la funcionalidad, que yo le he puesto a éste...

----------------------------------------------


...y bueno, se me ocurre que ya que me he tomado la molestia de hacer este control, documentaré todas las propiedades, y cuando lo recompile, lo dejaré disponible como recurso en el foro...  8) 8) 8)

« última modificación: Febrero 22, 2017, 01:56:19 pm por NEBIRE »

TOLO68

  • Bytes
  • *
  • Mensajes: 31
  • Reputación: +2/-0
    • Ver Perfil
Re:Rellenar con FloodFill usando GDI+ en VB6
« Respuesta #7 en: Febrero 23, 2017, 11:11:14 am »
Hola NEBIRE

El control que descargaste en la web, es el control antiguo que tenia, lo puse para ver las descargas que tiene, que en mi web solo ha tenido 5 o 6, pero en otras webs ya ha tenido 250, y de la web de controles que tenia antiguamente tuvo casi 3000, que no son muchas, pero claro es un control OCX, no es como un compresor ZIP o una utilidad de este tipo, que es usado en todos los ordenadores.

Lo que pasa es que cerraron el Hosting y ya no volví a poner la web en otro.

Por esto solo puse el DisplayHEX para poder descargar, porque asi puedo ver, si todavia la gente esta interesada en este tipo de controles.

Lo de la documentacion tambien tengo que hacerlo, y tambien tengo preparados los archivos PAD para los submit, pero claro todo eso lleva su tiempo :)

La Curiosidad que tenias de los 200K del control, era porque solo los bitmaps para las mascaras (habia 3, 1 por cada tamaño de display) ya ocupaban alrededor de 170K, porque los guarde en BMP a 16 millones de colores cuando basta guardarlos a 2 colores, con lo cual me han pasado a ocupar unos 10K :), algo que no tuve en cuenta anteriormente.

Ya que guardandolos en JPG aveces salen manchas o pixeles que no se ven a simple vista pero hacen funcionar mal la mascara.

De todas formas hoy en dia 200K no es nada para los discos duros que hay con cientos de GB, pero bueno ya se que tengo que hacer para otra vez :)

Lo de los digitos de 1 a 32, tambien lo podria hacer hasta 255, solo cambiando el 32 por 255 en una parte del codigo

Lo puse a 32, porque asi y todo encontre ya una exageracion un display de 32 digitos o mas.

Lo de no usar mascaras y hacerlo con lineas tambien tengo idea de hacerlo asi, y poder poner todos los tamaños que quiera.

De todas formas tambien me gustaria ver el tuyo, una vez que lo tengas acabado, y poder hacer comparaciones de velocidad y cosas así.

Asi competimos a ver quien hace el mejor display :D

Saludo desde España

:)

NEBIRE

  • Kilobyte
  • **
  • Mensajes: 50
  • Reputación: +6/-0
    • Ver Perfil
Re:Rellenar con FloodFill usando GDI+ en VB6
« Respuesta #8 en: Febrero 23, 2017, 09:35:34 pm »
jejeje... Si no se trata de competir. Se trata de hacer las cosas con sensatez.

Aún recuerdo aquellas palabras de Guillermo Puertas, cuando allá por los 80 soltó aquello de "64kb. (de memoria) debieran bastar para todos"... y ya ves, hoy la media ronda los 4gb. y parece ser insuficiente.

Los dias de la semana, es razonable limitarlos a 7, porque no hay más... pero si no hay complejidad añadida por el hecho de una mayor variedad, y tampoco acontece un problema de desbordamiento (255 digitos por 128pixeles que llegara a tener de ancho como maximo=32640, no llegando al limite del integer, no habría desbordamiento), es mejor no limitarlo basado en la creencia de que "deberia ser suficiente". Si no que dejarlo al límite natural. Si el 99% solo usará 4-8 digitos, que tenga un limite alto, no daña a nadie, a la vez que a ese 1%, no le fastidias... que luego andara como loco buscando una solución.

En general cuando uses imágenes,  escalarlas a mayor tamaño, suele dar mucho mejor resultado que a menor tamaño. El "downsampling", a pocos pixeles es letal, no hay manera de acertar con los detalles que son importantes. En estos casos es mejor "pintar" directamente, para tener un control férreo de la apariencia resultante. Poco importa que tengas una imagen buenísima a 512 píxeles, si hay que reducirla a 32, no tienes ningún control de qué detalles se perderán y cuales quedarán... sobretodo si ni siquiera el algoritmo de escalado es tuyo...

Ten en cuenta, que la calidad del control, exigirá buenos detalles. Ofrece variedad de propiedades, que el cliente no sienta que el control está demasiado limitado, porque si lo siente asi, buscara un sustituto... Huye también de darle funcionalidades peregrinas, que nunca nadie va a usar, queriendo justificar con ello, que "es mejor que aquel otro", por que "no tiene esto". Por ejemplo un display LCD, no necesita para nada un menú emergente, ni siquiera un ToolTipText.

Pero si puede aceptar de buen grado animarlo... desplazando el texto a derecha o izquierda, saliendo por el otro extremo y volviendo a entrar... de ese modo un texto/valor que no cabe en el display, se acaba viendo. Que es precisamente lo último que le haré yo al control, el próximo fin de semana.