Crear la clase EditorDibujos
Este
artículo es la continuación del anterior
Añadiremos un evento
a EditorDibujos
llamado Salvar que genere un
interfaz gráfico que sea un control de usuario
con interfaz gráfico y pinte en una matriz de 60x60 pixels esos puntos se salvarán
en la instancia CLineaPieza cuando se dispare el evento salvar.
1. Añadir
un UserControl al proyecto, llamado EditorDibujos, al crear
la clase como UserControl, Visual Studio nos permite generar todo el código
sobreescrito que necesitamos para un control de usuario. En último lugar,
podemos cambiar la declaración de la clase base para indicar que la clase base
es CEditorPieza
2. Abrir
el editor de la clase EditorDibujos en el diseñador de formularios
y poner la propiedad Size en la ventana de propiedades a 175, 150.
3. Añadir los
controles de la tabla que se muestra a continuación y poner sus propiedades
con los valores indicados.
Añadir un campo a EditorDibujos que defina los
puntos del dibujo. EditorDibujos el cual mantiene un array de puntos separado, copiado
como backup de la instancia CLineaPieza cuando el usuario pulsa el botón salvar.
Private m_puntos() As Point = New Point() {}
Añadir el
siguiente campo para referirse a la
instancia de CLineaPieza reeditando EditorDibujos manteniendo esta referencia y así pudiendo copiar el nuevo array de puntos después de hacer
click en el botón Salvar.
Private m_tipodibujo
As CLineaPieza
Añadir el
siguiente constructor para tomar un parámetro del objeto CLineaPieza. El
constructor debe copiar los puntos del objeto CLineaPieza al objeto EditorDibujos,
salvando la referencia al objeto CLineaPieza y asignando el método
de dibujo al control PictureBox.
Public Sub New(ByVal tipodibujo As CLineaPieza)
MyBase.New()
InitializeComponent()
ReDim Me.m_puntos(tipodibujo.Point.Length - 1)
tipodibujo.Punto.CopyTo(Me.m_puntos, 0)
AddHandler Me.PictureBox1.Paint, AddressOf
Me.Dibujar
m_tipodibujo = tipodibujo
End Sub
Añadir el método Dibujar al
control PictureBox .
Public Sub Dibujar(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.PaintEventArgs)
e.Graphics.DrawRectangle(New
Pen(Brushes.Black, 1), 0, 0, 60, 60)
Dim punto As Integer
For punto = 0 To m_puntos.Length
- 2
Dim one As Point = m_puntos(punto)
Dim two As Point = m_puntos(punto
+ 1)
e.Graphics.DrawLine(Pens.Black,
one, two)
Next
End Sub
Crear el
manejador de eventos para el evento mousemove del PictureBox y añadir el
siguiente código para mostrar las coordenadas en la etiqueta.
Private Sub pictureBox1_MouseMove(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.MouseEventArgs) Handles
PictureBox1.MouseMove
Me.Label1.Text = String.Format("({0}, {1})", e.X, e.Y)
End Sub
Crear el
manejador de evento para el evento MouseDown y añadir el siguiente código para
añadir un Nuevo punto al dibujo de la pieza y redibujar el PictureBox.
Private Sub pictureBox1_MouseDown(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.MouseEventArgs) Handles
PictureBox1.MouseDown
ReDim Preserve m_puntos(m_puntos.Length)
m_puntos(m_puntos.Length
- 1) = New Point(e.X, e.Y)
Me.Refresh()
End Sub
Hacer
doble click sobre el botón salvar para crear el evento del botón y añadir en
siguiente código para salvar los puntos de la instancia CLineaPieza y disparar el evento Salvar. El
evento RaiseSaved no debe aparecer en IntelliSense por que la clase base de
este punto es UserControl y no CEditarPieza.
Private Sub Salvar_Click(ByVal
sender As System.Object, ByVal e As
System.EventArgs) Handles Salvar.Click
m_tipodibujo.Puntos
= m_puntos
MyBase.RaiseSaved(Me,
New System.EventArgs())
End Sub
Modificar la declaración
de la clase para indicar que la clase deriva de la Clase CEditarPieza en lugar
de la clase UserControl.
Public Class EditorDibujos
Inherits CEditorPieza
End Class
Crear la clase CBitmapPieza
Para
crear la clase CBitmapPieza se debe
implementar otra vez un par de clases que derivan de las clases CPieza and CEditarPieza. La
clase CBitmapPieza mantiene el nombre del archivo bitmap para la pieza. CBitmapPiezaEditor mantiene
una referencia a la instancia CBitmapPieza y una copia del archivo bitmap. Después
de usar, seleccionar un nuevo fichero bitmap y pulsar sobre el botón Salvar, el
nuevo nombre de fichero se guarda en una instancia de CBitmapPieza.
Añadir una nueva clase al
proyecto y llamarla CBitmapPieza.
Modificar la declaración
de la clase para indicar que la clase deriva de la clase CPieza.
Public Class CBitmapPieza
Inherits CPieza
Public Overrides Function Clone() As
CPieza
End Function
Public Overrides Sub Dibujar(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.PaintEventArgs)
End Sub
Public Overrides Function ObtenerEditor() As
CEditorPieza
End Function
End Class
Añadir el siguiente campo
y propiedad para almacenar el nombre de fichero del bitmap:
Private m_piezabitmap
As String = ""
Public Property BitmapFile() As
String
Get
Return (m_piezabitmap)
End Get
Set(ByVal Value As String)
m_piezabitmap
= Value
End Set
End Property.
Definir el método Dibujar, exactamente
como el de la clase CLineaPieza, la codificación del interfaz de usuario debe usar este método
para mostrar la pieza.
Public Overrides Sub
Dibujar(ByVal sender As
Object, ByVal e
As System.Windows.Forms.PaintEventArgs)
e.Graphics.DrawImage(New _
System.Drawing.Bitmap(m_piezabitmap), 0, 0)
End Sub
Definir el método ObtenerEditor. Saldrá un error en este punto porque aún no se he implementado la clase CBitmapPiezaEditor.
Public Overrides Function ObtenerEditor()
As CEditorPieza
Return New CBitmapPiezaEditor(Me)
End Function
Definir el método Clone.
Public Overrides Function
Clone() As CPieza
Dim newTipodibujo
As New CBitmapPieza()
newTipodibujo.BitmapFile = Me.BitmapFile
Return (newTipodibujo)
End Function
Crear la claseCBitmapPiezaEditor
La clase CBitmapPiezaEditor
necesita solo buscar y guardar. Botones salvar y un picturebox para mostrar los archivos
bitmap.
Añadir
una nueva clase UserControl al proyecto. Llamarla CBitmapPiezaEditor.
Abrir CBitmapPiezaEditor en el
diseñador y poner la propiedad Size a 175, 150 en la ventana de propiedades.
Añadir
los siguientes controles y poner sus propiedades como las mostradas en la tabla.
Abrir la
clase CBitmapPiezaEditor con el editor de código y añadir un campo al
archivo bitmap. La clase CBitmapPiezaEditor mantiene una referencia separada al nombre de
archivo que se copió en la instancia de CBitmapPieza cuando
el usuario pulsa el botón Salvar.
Private m_ficheroBitmap
As String
Añadir un
campo para referirse a la instancia CBitmapPieza. CBitmapPiezaEditor mantiene
esta referencia así que copia el nombre del archivo bitmap en CBitmapPieza cuando
el usuario pulsa el botón salvar.
Private m_tipodibujo
As CBitmapPieza
Añadir el
siguiente constructor, el cual toma un parámetro, una instancia de CBitmapPieza.
El
constructor copiará el nombre de archivo de CBitmapPieza a CBitmapPiezaEditor,
salvando la referencia a CLineaPieza y asignando un método de dibujo al control PictureBox.
Public Sub New(ByVal tipodibujo As CBitmapPieza)
MyBase.New()
InitializeComponent()
m_tipodibujo = tipodibujo
m_piezabitmap = tipodibujo.BitmapFile
AddHandler Me.PictureBox1.Paint, AddressOf
Me.Dibujar
End Sub
Añadir el método dibujar.
Public Sub Dibujar(ByVal
sender As Object,
ByVal e As
System.Windows.Forms.PaintEventArgs)
e.Graphics.DrawImage(New Bitmap(m_piezabitmap),
0, 0)
End Sub
Crear el
manejador de evento para el botón buscar y añadir este código para mostrar la
caja de dialogo.
Private Sub Buscar_Click(ByVal
sender As System.Object, ByVal e As
System.EventArgs) Handles Buscar.Click
OpenFileDialog1.ShowDialog()
If (Me.OpenFileDialog1.FileName.Length
<> 0) Then
m_piezabitmap
= Me.OpenFileDialog1.FileName
Me.PictureBox1.Refresh()
End If
End Sub
Crear el
manejador del evento Click del botón salvar y añadirle este código para salvar
en fichero y guardarlo en una instancia de CBitmapPieza al
ejecutar el evento salvar.
Private Sub Salvar_Click(ByVal
sender As System.Object,ByVal e As System.Eve ntArgs) Handles Salvar.Click
m_tipodibujo.BitmapFile
= m_piezabitmap
MyBase.RaiseSaved(Me,
New System.EventArgs())
End Sub
El Interfaz de usuario
La implementación para dibujar la pieza como
bitmap es diferente, sin embargo el código del interfaz de usuario, es muy
simple y no revela las diferencias entre los dos tipos de piezas dibujadas.
Crear los elementos del interfaz de usuario
El
interfaz de usuario contiene paneles para plantillas y para piezas editadas y un
área para editar piezas.
Abrir el
diseñador del formulario form1, en la ventana de propiedades, cambiar la
propiedad Size del form1 y ponerla a 344,392.
Añadir
los siguientes controles al formulario.
Con lo que el interfaz de
usuario queda así:
La clase CPieza muestra cada pieza gracias al método Dibujar, y no contiene ningún tipo de elemento que pueda
mostrar en un formulario, tal y como un control panel con una imagen o un PictureBox.
Añadir la
siguiente mini clase, BotonPieza, después del final la clase Form1. Este control de usuario creado
por el cliente se usa para mostrar las piezas en plantillas y en paneles de
piezas.
Public Class BotonPieza
Inherits UserControl
Private m_pieza As
CPieza
Public Sub New(ByVal nuevaPieza As CPieza)
Me.Size = New
Size(61, 61)
m_pieza =
nuevaPieza
AddHandler
Me.Paint, AddressOf
nuevaPieza.Dibujar
End Sub
Public Property
Pieza() As CPieza
Get
Return (m_pieza)
End Get
Set(ByVal Value As CPieza)
m_pieza =
Value
End Set
End Property
End Class
Hay que
notar que le uso del método Dibujar de CPieza es como el método Paint del
control. En definitiva consiste en añadir una pieza a la instancia como una
propiedad del control.
Crear las instancias de la plantilla
Las plantillas de las piezas
son instancias de cada clase CLineaPieza y CBitmapPieza que se
muestran en el control de usuario BotonPieza. Las instancias de BotonPieza se añaden
al panel de plantillas.
Esta es
sólo la parte del código de la interfaz de usuario que necesita para crear la clase CPieza. No hay necesidad de agregar
más de una instancia de CBitmapPieza en el
panel de plantillas. Es mejor añadir múltiples instancias de CLineaPieza, ya que el
usuario puede guardarlas para cuando tenga que volver a crear dibujos con una base común. Si se extiende la aplicación para
añadir más tipos de piezas, se necesitaría este código para modificarlo. El
resto de la aplicación se ocupará de las instancias CLineaPieza y CBitmapPieza usando las referencias de la clase base CPieza.
Hacer
doble click en el diseñador del formulario para crear el evento Form_Load y añadir
el siguiente código al evento para añadir instancias de CPieza al panel
de plantilla.
Private Sub Form1_Load(ByVal
sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim Dibujo1 As New CLineaPieza()
Dibujo1.Puntos
= New Point() {New
Point(0, 30), New Point(60, 30), New Point(60, 0), New
Point(30, 0), New Point(30, 60)}
Dim Dibujo2 As New CLineaPieza()
Dibujo2.Puntos
= New Point() {New
Point(30, 0), New Point(60, 30), New Point(30, 60), New
Point(0, 30), New Point(30, 0), New Point(0, 0)}
Dim bitmap1 As New CBitmapPieza()
bitmap1.BitmapFile
= "CarpetaProyecto\CaballoBlanco.bmp"
Dim tipodibujos()
As CPieza = {Dibujo1, bitmap1, Dibujo2}
Dim pt As Integer
For pt = 0 To tipodibujos.Length
- 1
Dim button As New BotonPieza(tipodibujos(pt))
button.Top
= 70 * pt
button.Left
= 5
AddHandler button.Click, AddressOf
Me.Plantilla_Click
Me.Plantillas.Controls.Add(button)
Next
End Sub
Editar y salvar las nuevas piezas
El uso de las instancias de CLineaPieza y CBitmapPieza se hace a través de las variables de referencia de CPieza. Como se ha dicho antes se simplifica la
programación gracias al uso de polimorfismo, reduciendo el número de nombres de
clase con las que hay que trabajar Si hay que añadir otros tipos de pieza, no hay que cambiar el código.
A continuación se añade el siguiente código al
formulario al método Pieza_Click y se añade un campo para referirse a la nueva instancia CPieza. Hay
que tener en cuenta que da igual en qué plantilla se ha hecho click, o si el tipo de esa instancia es CLineaPieza o CBitmapPieza. Porque CEditarPieza deriva de UserControl, no importa
si la instancia, devuelve una instancia de EditorDibujos o CBitmapPiezaEditor.
Private
m_nuevaPieza As CPieza = Nothing
Private Sub Pieza_Click(ByVal
sender As Object,
ByVal e As
System.EventArgs)
Dim button As
BotonPieza = CType(sender, BotonPieza)
m_nuevaPieza
= button.Pieza.Clone()
Dim
designer As CEditorPieza = m_nuevaPieza.ObtenerEditor()
designer.Location = New Point(10,
10)
Me.Editor.Controls.Add(designer)
AddHandler designer.Saved, AddressOf
Me.PiezaSalvada
End Sub
Finalmente
añadiremos el siguiente código para el método PiezaSalvada.
Esto agrega una pieza en el panel de piezas. Una vez que la pieza se guarda, el
control de CEditarPieza no tiene ningún propósito. Con
lo que se desecha de modo que no utiliza más recursos del sistema. Debido a que
controlamos el código, sabemos que el parámetro enviado en el evento PiezaSalvada es
una instancia de CEditarPieza. Esto envía un parámetro que
se puede controlar con un cast.
Private Sub PiezaSalvada(ByVal
sender As Object,
ByVal e As
EventArgs)
Me.Controls.Remove(CType(sender, Control))
CType(sender,
Control).Dispose()
Dim pb As BotonPieza = New
BotonPieza(m_nuevaPieza)
pb.Left = Me.Piezas.Controls.Count
* 70
pb.Top = 5
pb.Enabled = False
Me.Piezas.Controls.Add(pb)
End Sub
Todo lo que necesita el código del interfaz de usuario es una pequeña
clase y tres controladores de eventos. Gran parte del trabajo se mete en las
clases CPieza y CEditarPieza.
Para probar la aplicación presionar
F5 para ejecutar. El siguiente gráfico muestra los resultados después de añadir nuevos modelos de piezas.
No hay comentarios:
Publicar un comentario