Me gusta el código Leandro, aunque creo que a Tolo68, le bastaba el código anterior...
Después de todo, es que creo que no acaba de entender el concepto de Backbuffer. Así que se lo explico más claramente a ver si lo entiende:
Cuando necesitas dibujar y 'pegar' con transparencia, es lo mismo que dibujar un fondo (llamémosle el picture destino), e ir dibujando encima el resto de cosas y capas, en el orden adecuado (si unas cubren partes de otras), esto último equivale a 'pegar' otro picture con transparencia, pero la diferencia radical es la velocidad que implica, ya que no necesitas pegar todo un picture sobre el otro, si no pequeñas partes.. líneas por aquí y allá, arcos, flechas, númeritos, etc...
Para todo eso, VB6 basta por sí mismo, pero si necesitas algo de más calidad gráfica y también algo más de velocidad, efectivamente recurrir a GDI (o GDI+), es buena solución, pero no cambia el concepto, en nada, sólo cambia por decirlo así, la 'máquina de pintar'...
Entonces si yo fuera tú, me quedaba con el código del proyecto anterior que te puso Leandro... con las siguientes modificaciones:
A - En otro picturebox (mejor si creas un DC en memoria, ya que usas GDI, como ya he comentado otras veces) allí pegas el fondo siempre, dado que el fondo no va a variar, básicamente, puede permanecer en un Ipicturedisp (Picture) o en un hBitmap y la primera operación es pegar ese fondo en el DC en memoria (o picturebox oculto).
B - Cuando salta un evento resize en el usercontrol, CALCULAS y solo calculas, las posiciones de la aguja para los 90º... y los retienes en un array, esto es CordenadasDestino(0 to 89) as Point (el origen taambién se recalcula en es emomento, pero es 1solo punto.
C - Cuando necesitas redibujar la aguja a otra postura (cambió el valor que actúa sobre la aguja, el ángulo), y cuando hay un resize, y cuando se cambia algún aspecto (propiedad) modificable por el cliente, como el BackColor, o el 'ArcColor', etc... se invoca una rutina RedibujarTodo.
D1 - Si el control no tiene autoRedraw, activado, en el método Usercontrol_Paint invocas RedibujarTodo (ya que sin autoRedraw, cuando otro objeto 'pise' el usercontrol se borrará y será necesario redibujarlo.
D2 - Si el control tiene activado AutoRedraw, desde donde se precisa se invoca 'RedibujarTodo' y el método Usercontrol_Paint (el evento Paint del usercontrol), no se necesita.
E - El método, RedibujarTodo, lo que hace entonces es pegar el fondo en un DC del mismo tamaño que el usercontrol, luego pegas los textos de los números 0, 15, 30, 45, 60, 75, 90, 105, 120, 135 sobre el arco (encima de ellos) y quizás unas líneas o unos puntos en esos ángulos. Todo esto incluso podría ser el propio fondo ya predibujdo con un programa gráfico y precargado en un Ipcituredisp y finalmente pegas la aguja sin necesidad de recalcular cada vez su posición (ya se conocen sus puntos de destino, son los mismos precalculados, cuando se redimensiona el control... basta calcular los 136, más el de origen una sola vez, cuando se Redimensiona el usercontrol.
F - Finalmente el backbuffer se pega en el usercontrol de destino (painpicture, BitBlt...)
Esto es rápido, limpio, fácil de modificar y libre de parpadeos.
Y dado que el backbuffer siempre se dibuja fuera de la vista, no se pierde tiempo en actualizar la vista, y cuando se vuelca al usercontrol es una operación muy muy muy rápida, una sola operación gráfica de refresco del control, lo que agiliza mucho la visualización sin sobrecarga... ya que cada vez que pintas algo en un objeto que está visible (en primer plano), debe actualizarse el gráfico al completo, así sea solo un único pixel lo que cambie, por eso, pintar sobre la marcha muchos trazos gráficos, es una sobrecarga inútil, y lastrante... para cosas de poca monta, pruebas... está bien, para algo más 'profesional', no es lo adecuado.
De hecho, si alguna vez has cargado un listbox, con miles de entradas (intenta 100.000), verás que es lentísimo... porque a cada entrada, se actualiza el gráfico (se redibuja al completo el Listbox, lo cual se puede observar sobre las barras de scroll, donde el deslizador debe actualizarse para ajustarse al tamaño y altura en función del alto del listbox y el número de ítems que contiene). Pués bien, si antes de añadir las entradas, se hace un:
ListBox1.visible= false
Y luego se cargan las miles de entradas del listbox, y cuando se hayan cargado todas, de nuevo se hace visible el listbox, se observará que el tiempo de carga se ha reducido drásticamente por 10-100 veces... con los objetos gráficos, sucede lo mismo... para tener en refreshRate alto (como pareces indicar a Leandro, en su último código), es preciso dibujar todo en un backbuffer y volcar luego un único gráfico al lienzo destino.
Dibujar un objeto gráfico, en una zona con un fondo que luego hay que detectar para hacerlo transparente, es mal planteamiento (perfectamente aceptable, para pruebas y demostraciones, pero no para un código definitivo), ya que si se parte del fondo que originalmente habrá de ser, ya no se precisa hacer esa operación (que puede consumir su tiempo)... el color de máscara, es más bien, para cuando se cargan imágenes externas que obviamente no tienen de fondo lo que tu deseas (por ejemplo Sprites), es decir cuando la situación es compleja y tan cambiante que no hay un fondo fijo... y debe recrearse nuevamente cada vez con objetos complejos tal que redibujarlos o calcularlos cada vez, es lento y se opta por tener imágenes ya precalculadas, tal y como se hace en los videojuegos... en tu caso, como solo consta de dos arcos quizás unos textos con números y una aguja, no hay mucha diferencia entre tener ya un fondo gráfico elaborado y cargado en una imagen que trazarlo all actualizar la imagen, en cuanto a rendimiento (si te aclaro que es más rápido pegar una imagen ya que es solo transferencia de memoria, no hay cálculos de por medio)...
También si necesitas más velocidad, olvida operar con single y double, opera con integer o long, poco importa la precisión de un ángulo si por redondeo es un píxele más allá o más acá. Siempre y cuando no sean cálculos acumulativos...
Saludos...