Formularios con forma en VB .NET

Aplicar regiones a un formulario usando objetos GraphicsPath.AddLine y GraphicsPath.AddEllipse para recortar el área del formulario y cambiar la forma de la ventana, en Visual Studio 2017 con VB

Utilizando objetos de la clase GraphicsPath y aplicando regiones de recorte es sencillo modificar la forma de la ventana de un formulario. Podemos darle prácticamente cualquier aspecto pero, por sencillez del código, en este ejercicio nos restringiremos a 3 formas, círculo, rombo y polígono, usando regiones de recorte con el aspecto deseado.

GraphicsPath del espacio de nombres System.Drawing.Drawing2D representa una serie de líneas y curvas conectadas. La base del ejercicio es:

  • ventana redondeada: en el evento Paint de un PictureBox o del formulario se dibuja sobre GraphicsPath una región de recorte de forma circular con el método AddEllipse y se convierte en la región visible del formulario
  • ventana romboidal y poligonal: en el evento Load del formulario se van añadiendo líneas definidas por su punto x.y de inicio y de final con coordenadas absolutas calculadas respecto a la ventana visible del formulario. Cada segmento de línea se añade con GraphicsPath.AddLine(Int32, Int32, Int32, Int32) a la figura actual.

Los 4 parámetros Int32 de AddLine son: coordenada x del punto inicial de la línea, coordenada y del punto inicial de la línea, coordenada x del punto final de la línea, coordenada y del punto final de la línea.

Imagen del formulario romboidal

Código en Visual Basic .NET

Nota: La presentación de este tipo de formularios queda mejor si en el diseñador de VS configuramos su propiedad FormBorderStyle en none.

Para conseguir el aspecto de un formulario redondeado:

' ACTUAMOS EN EL EVENTO PAINT DEL FORMULARIO O EN EL DEL CONTROL PICTUREBOX
Private Sub F1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
	' Se crea un objeto de la clase GraphicsPath
	Dim gp As GraphicsPath = New GraphicsPath
	' Rectángulo para hacer el recorte
	Dim rect As Rectangle
	' La imagen utilizada mide 440x440 por lo que el rectángulo no debe ser mayor para que se vea bien
	' Las medidas (0, 0, 440, 440) equivalen a (Left, Top, Width, Height) del formulario
	rect = New Rectangle(0, 0, 440, 440)
	' Método que superpone una figura (círculo en este caso) al objeto GraphicsPath
	gp.AddEllipse(rect)
	' Región que se crea a partir del objeto GraphicsPath recortado
	Dim reg As Region
	reg = New Region(gp)
	' Esta es la región visible del formulario
	Me.Region = reg
	' Mejorar el aspecto del borde redondeado aplicando antialias
	e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
End Sub

Para conseguir el aspecto de un formulario romboidal:

'ACTUAMOS EN EL EVENTO LOAD  DEL FORMULARIO
Private Sub F2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
	' Se crea un objeto de la clase GraphicsPath
	' Para determinar cómo se rellena su interior se usa como parámetro un objeto de la emumeración FillMode que tiene 2 miembros:
	' Alternate (por defecto) y Winding. El modo determina cómo se rellena y recorta el interior de una figura cerrada
	Dim GP As GraphicsPath = New GraphicsPath(FillMode.Alternate)
	' Se van añadiendo líneas definidas por su punto x.y de inicio y de final con coordenadas absolutas calculadas respecto a la ventana visible del formulario
	' GraphicsPath.AddLine(Int32, Int32, Int32, Int32) agreda un segmento de línea a la figura actual. Parámetros
	' x1 Int32 coordenada x del punto inicial de la línea, y1 Int32 coordenada y del punto inicial de la línea
	' x2 Int32 coordenada x del extremo de la línea, y2 Int32 coordenada y del extremo de la línea
	' La imagen mide 440x440 y la mitad de 440 es 220, estas medidas junto con el valor cero se utilizan para dibujar el rombo
	GP.AddLine(0, 220, 220, 0)
	GP.AddLine(220, 0, 440, 220)
	GP.AddLine(440, 220, 220, 440)
	GP.AddLine(220, 440, 0, 220)
	' Recortar el objeto GraphicsPath con la forma generada por las líneas
	Me.Region = New Region(GP)
End Sub

Para conseguir el aspecto de un formulario poligonal:

'ACTUAMOS EN EL EVENTO LOAD  DEL FORMULARIO
Private Sub F3_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
	' Se crea un objeto de la clase GraphicsPath
	' Para determinar cómo se rellena su interior se usa como parámetro un objeto de la emumeración FillMode que tiene 2 miembros:
	' Alternate (por defecto) y Winding. El modo determina cómo se rellena y recorta el interior de una figura cerrada
	Dim GP As GraphicsPath = New GraphicsPath(FillMode.Alternate)
	' Se van añadiendo líneas, definidas por su punto x.y de inicio y de final con coordenadas absolutas calculadas respecto a la ventana visible del formulario
	' GraphicsPath.AddLine(Int32, Int32, Int32, Int32) añade un segmento de línea a la figura actual. Parámetros
	' x1 Int32 coordenada x del punto inicial de la línea, y1 Int32 coordenada y del punto inicial de la línea
	' x2 Int32 coordenada x del extremo de la línea, y2 Int32 coordenada y del extremo de la línea
	' La imagen mide 440x440 y se usan las medidas 88 (440/5) y 352 (88*4) que se utilizan para dibujar el polígono
	GP.AddLine(88, 0, 352, 0)
	GP.AddLine(352, 0, 440, 440)
	GP.AddLine(440, 440, 0, 440)
	GP.AddLine(0, 440, 88, 0)
	' Recortar el objeto GraphicsPath con la forma generada por las líneas
	Me.Region = New Region(GP)
End Sub

Se puede comprender mejor cómo configurar las líneas de recorte con esta imagen referida a la ventana romboidal:

Control Button transparente

En algunas ocasiones puede ser conveniente que las botones aplicados sobre la imagen de un PictureBox (o cualquier otro control) tengan su fondo transparente. Para que Button sea transparente hay que establecer su propiedad BackColor en Color.Transparent.
La propiedad BackColor es una propiedad de ambiente. Una propiedad de ambiente es una propiedad del control que, si no se establece, se recupera del control principal. Por ejemplo, de forma predeterminada el control Button tendrá la misma propiedad BackColor que su control Form principal.
Si hay otro control entre el control actual (Button) y el primario correspondiente (Form), Button no mostrará el color del control situado entre ambos sino el del control primario (Form). Por ejemplo, los botones transparentes situados sobre un PictureBox cogen el color de fondo del formulario y no el del PictureBox (que es el control intermedio).
Podríamos hacer que el botón se configurase con el color de fondo de la imagen del PictureBox añadiéndolo al grupo de controles del PictureBox con el método Controls.Add, de esta manera PictureBox se convierte en el control primario de Button (en lugar de Form) y es con él con el que simula la transparencia.

Me.PictureBox1.Controls.Add(Me.Button1)

En este ejercicio esto se aplica a los botones colocados sobre la imagen de fondo de los formularios con forma que, al ser pulsados, cierran la ventana. En los recortes de tipo romboidal y poligonal la imagen está colocada directamente como fondo del formulario que de esta forma es el control padre del botón y, sin necesidad de código adicional, el botón obtiene por transparencia el color de la imagen que tiene debajo con la condición de tener estas 2 propiedades:

Me.BtCerrar.BackColor = System.Drawing.Color.Transparent
Me.BtCerrar.UseVisualStyleBackColor = True

En el recorte de tipo circular se ha interpuesto un PictureBox que es el que se rellena con la imagen. Si en las propiedades del botón colocamos el código anterior sin más, el resultado es que el botón no se ve porque coge el color del Formulario y no el de la imagen. Hay que añadir el botón al grupo de controles del PictureBox y de esta forma el botón coge el color de la imagen y se muestra correctamente.

Private Sub FormCircular_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.PBox1.Controls.Add(Me.BtCerrar)
End Sub

Aplicación completa en Visual Studio 2017: aquí.

Deja un comentario

Tu dirección de correo electrónico no será publicada.