none
GDI+. Falla al tratar de hacer Zoom respecto a la posición del Mouse o Pan a la primera vez. RRS feed

  • Debate general

  • Muy buenas noches a todos, la verdad le he hechado cabeza a ésto, pero ya no se que hacer. Verán, estoy tratando de crear un control para dibujar con GDI+ formas sencillas, y todo iba bien hasta que me pasa lo siguiente:

    * Al tratar de hacer Zoom o Pan con respecto a la posición actual del Mouse, a la primera vez que quiero hacerlo en el control, de alguna manera falla, pues siempre lo hace con respecto al (0,0) del control, a cuyo Graphics le hago una transformación de sus ejes, y su origen lo tengo en la esquina inferior izquierda del control, y con el EJE Y positivo hacia arriba. Sin embargo, luego de que tengo la primera interración de Zoom(MouseWheel) o Pan(MouseDown y MouseMove), funciona de maravilla.

    El código es algo largo, pero lo voy a colocar, para que por favor un alma amiga me pueda ayudar.

    Public Class ModelControl
    
    #Region "Variables"
    
    #Region "Líneas de referencia del Mouse"
    
        ''' <summary>
        ''' Color de las líneas de Referencia del Mouse que se dibujan una horizontal y otra vertical
        ''' mientras se mueve el Mouse por el control.
        ''' </summary>
        Private _LineasReferenciaMouse_Color As Color = Color.Black
        ''' <summary>
        ''' Grosor o ancho de las líneas de Referencia del Mouse que se dibujan una horizontal y otra vertical
        ''' mientras se mueve el Mouse por el control. El ancho debe ingresarse en milímetros.
        ''' </summary>
        Private _LineasReferenciaMouse_GrosorMM As Single = 0.05F
        ''' <summary>
        ''' Indica si las líneas de referencia del Mouse se dibujarpan en el control.
        ''' </summary>
        Private _LineasReferenciaMouse_Dibujar As Boolean = False
        ''' <summary>
        ''' Tipo de línea que se mostrará cuando se dibuje las líneas de referencia del Mouse.
        ''' </summary>
        Private _LineasReferenciaMouse_TipoLinea As LineaReferenciaMouse_Tipo = LineaReferenciaMouse_Tipo.Discontinua
    
    #End Region
    
    #Region "Zoom y Pan del Mouse"
    
        ''' <summary>
        ''' Indica si el Graphics del control debe actualizarse con los eventos del Mouse,
        ''' para los casos de Zoom y Pan.
        ''' </summary>
        Private _isZoomPan_MouseEvent As Boolean = False
        ''' <summary>
        ''' Indica si el Graphics del control debe actualizar el dibujo para que se ajuste a la pantalla
        ''' con las dimensiones actuales. Esta variable se activa con un Button en su evento Clik.
        ''' </summary>. Por defecto indicamos que el dibujo se cargue centrado y ajustado a la pantalla del control.
        ''' Es necesario para la primera vez que se carge el Form donde se encuentre el control.
        Private _isFitDrawingToControl_ClikButton As Boolean = True
        ''' <summary>
        ''' Verifica si un botón del Mouse se ha presionado dentro de un control.
        ''' </summary>
        Private _mouseDownPress As Boolean = False
        ''' <summary>
        ''' Variable que guarda posición del Mouse en el evento Down de un control. Esto
        ''' ocurre cuando se presiona un botón del Mouse en un control.
        ''' </summary>
        Private _mouseDown_Location As New PointF
        ''' <summary>
        ''' Posición actual del mouse cuando se activa el evento MouseMove.
        ''' </summary>
        Private _mousePositionMove As New PointF(MousePosition.X, MousePosition.Y)
        ''' <summary>
        ''' Traslado del origen de coordenadas en el eje X con el zoom previo.
        ''' </summary>
        Private _TraslationX_Graphics_old As Single
        ''' <summary>
        ''' Traslado del origen de coordenadas en el eje Y con el zoom previo.
        ''' </summary>
        Private _TraslationY_Graphics_old As Single
        ''' <summary>
        ''' Variable para guardar el valor que debe trasladarse el Objeto Graphics en el eje X, durante el Zoom
        ''' para que siempre el foco del zoom sea de acuerdo a la posición del punntero del Mouse.
        ''' </summary>
        Private _TraslationX_Graphics As Single
        ''' <summary>
        ''' Variable para guardar el valor que debe trasladarse el Objeto Graphics en el eje Y, durante el Zoom
        ''' para que siempre el foco del zoom sea de acuerdo a la posición del punntero del Mouse.
        ''' </summary>
        Private _TraslationY_Graphics As Single
        ''' <summary>
        ''' Escala de zoom que debe aplicarse en ScaleTransform del Graphics, el cual se aciva con el evento MouseWheel.
        ''' </summary>
        Private _zoom As Single = 1.0F
        ''' <summary>
        ''' Escala del zoom inmediatamente anterior del que ahora tiene la variable zoom. Esta variable siempre se calcula
        ''' en el evento MouseWheel.
        ''' </summary>
        Private _zoom_old As Single = 1.0F
        ''' <summary>
        ''' Incremento del zoom que se realiza en el evento MouseWheel.
        ''' </summary>
        Const _zoom_increment As Single = 0.1F
        ''' <summary>
        ''' Mínimo zoom que se puede aplicar a los dibujos.
        ''' </summary>
        Const _zoom_min As Single = 0.1F
        ''' <summary>
        ''' Máximo zoom que se puede aplicar a los dibujos.
        ''' </summary>
        Const _zoom_max As Single = 5.0F
    
    #End Region
    
    #Region "Graphics de la Clase"
    
        ''' <summary>
        ''' Graphics obtenido del evento Paint del Control.
        ''' </summary>
        Private _graphicsControl As Graphics
        ''' <summary>
        ''' Indica la calidad con los que se dibujará en el Graphics del control.
        ''' Por defecto se coloca en calidad.
        ''' </summary>
        Private _graphicsControl_Quality As SmoothingMode = SmoothingMode.HighQuality
        ''' <summary>
        ''' Indica el color que se usará para hacer el borrado del Graphics mediante el método <seealso cref="Graphics.Clear(Color)"/>
        ''' </summary>
        Private _graphicsControl_ClearColor As Color = Color.White
    
    #End Region
    
    #Region "Dibujar ejes X-Y"
    
        ''' <summary>
        ''' Verifica si se desea dibujar los ejes X-Y en la esquina inferior izqueirda del control
        ''' </summary>. Por defecto se indica que si.
        Private _dibujarEjesControl As Boolean = True
        ''' <summary>
        ''' Color con que se dibujará los ejes X-Y en la parte inferior izquierda del control.
        ''' </summary>
        Private _dibujarEjesControl_Color As Color = Color.DarkBlue
        ''' <summary>
        ''' Letra que se usará para e Eje Horizontal. Por defecto es X.
        ''' </summary>
        Private _dibujarEjesControl_LetraEjeHorizontal As String = "X"
        ''' <summary>
        ''' Letra que se usará para el Eje Vertical. Por defecto es Y.
        ''' </summary>
        Private _dibujarEjesControl_LetraEjeVertical As String = "Y"
    
    
    #End Region
    
    #End Region
    
    #Region "Propiedades"
    
    #Region "Líneas de referencia del Mouse"
    
        ''' <summary>
        ''' Color que se usará para dibujar las líneas de referencia del mouse en el control.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(True)>
        <Category("Líneas referencia mouse"), Description("Color con el que se dibujará líneas de referencia del mouse.")>
        Public Property LineasReferenciaMouse_Color As Color
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _LineasReferenciaMouse_Color
            End Get
            Set(value As Color)
                'Se actualiza el valor de la variable de la clase
                'con la que trabaja esta propiedad.
                _LineasReferenciaMouse_Color = value
                'Actualizamos en el evento Paint, para que se vea reflejado el cambio de inmediato
                'cuando se está con el control en modo Diseño.
                Me.Refresh()
                '
            End Set
        End Property
    
        ''' <summary>
        ''' Indica si se dibujarán las líneas de referencia del Mouse en el control.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(False)>
        <Category("Líneas referencia mouse"), Description("Indica si las líneas de referencia del Mouse se dibujarán en el control.")>
        <DefaultValue(True)>
        Public Property LineasReferenciaMouse_Dibujar As Boolean
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _LineasReferenciaMouse_Dibujar
            End Get
            Set(value As Boolean)
                'Se actualiza el valor de la variable de la clase
                'con la que trabaja esta propiedad.
                _LineasReferenciaMouse_Dibujar = value
                '
            End Set
        End Property
    
        ''' <summary>
        ''' Tipo de línea que se mostrará cuando se dibuje las líneas de referencia del mouse.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(True)>
        <Category("Líneas referencia mouse"), Description("Tipo de línea que se mostrará cuando se dibuje las líneas de referencia del mouse.")>
        <DefaultValue(LineaReferenciaMouse_Tipo.Discontinua)>
        Public Property LineasReferenciaMouse_TipoLinea As LineaReferenciaMouse_Tipo
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _LineasReferenciaMouse_TipoLinea
            End Get
            Set(value As LineaReferenciaMouse_Tipo)
                'Se actualiza el valor de la variable de la clase
                'con la que trabaja esta propiedad.
                _LineasReferenciaMouse_TipoLinea = value
                '
            End Set
        End Property
    
    #End Region
    
    #Region "Zoom y Pan del control"
    
        ''' <summary>
        ''' Asigna o retorna si el Graphics del control entra en modo de Zoom o Pan.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(False)>
        <Category("Mis Propiedades. Zoom y Pan."), Description("Indica si el Graphics del control entra en modo de Zoom.")>
        Public Property IsZoomPan_MouseEvent As Boolean
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _isZoomPan_MouseEvent
            End Get
            Set(value As Boolean)
                'Asigna a la propiedad de la clase el valor que se retorna.
                _isZoomPan_MouseEvent = value
            End Set
        End Property
    
    #End Region
    
    #Region "Ajustar dibujo a tamaño actual del control"
    
        ''' <summary>
        ''' Asigna o retorna un valor que indica si el dibujo del <seealso cref="Graphics"/> del control debe ajustarse al tamaño
        ''' actual del control. Debe activarse desde el evento <seealso cref="Click"/> de un Botòn.
        ''' </summary>
        <Browsable(False)>
        <Category("Mis Propiedades. Ajustar dibujo a control."), Description("Indica si el dibujo del Graphics del control debe ajustarse al tamaño actual mismo.")>
        Public Property IsFitDrawingToControl_ClikButtonEvent As Boolean
            Get
                '
                'Retorna el valor de la propiedad.
                Return _isFitDrawingToControl_ClikButton
                '
            End Get
            Set(value As Boolean)
                'Se asigna el valor de la propiedad privada de la Clase.
                _isFitDrawingToControl_ClikButton = value
            End Set
        End Property
    
    #End Region
    
    #Region "Dibujar ejes X-Y"
    
        ''' <summary>
        ''' Letra que se usará para mostrar en el Eje Horizontal.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(True)>
        <Category("Ejes Globales"), Description("Letra que se usará para el Eje Horizontal.")>
        Public Property EjesGlobales_LetraEjeHorizontal As String
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _dibujarEjesControl_LetraEjeHorizontal
            End Get
            Set(value As String)
                'Se actualiza el valor de la variable de la clase
                'con la que trabaja esta propiedad. Quitamos espacios en Blanco.
                _dibujarEjesControl_LetraEjeHorizontal = Trim(value)
                'Actualizamos en el evento Paint, para que se vea reflejado el cambio de inmediato
                'cuando se está con el control en modo Diseño.
                Me.Refresh()
                '
            End Set
        End Property
    
        ''' <summary>
        ''' Letra que se usará para mostrar en el Eje Vertical.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(True)>
        <Category("Ejes Globales"), Description("Letra que se usará para el Eje Vertical.")>
        Public Property EjesGlobales_LetraEjeVertical As String
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _dibujarEjesControl_LetraEjeVertical
            End Get
            Set(value As String)
                'Se actualiza el valor de la variable de la clase
                'con la que trabaja esta propiedad. Quitamos espacios en Blanco.
                _dibujarEjesControl_LetraEjeVertical = Trim(value)
                'Actualizamos en el evento Paint, para que se vea reflejado el cambio de inmediato
                'cuando se está con el control en modo Diseño.
                Me.Refresh()
                '
            End Set
        End Property
    
        ''' <summary>
        ''' Indica si se desea dibujar los ejes X-Y en la parte inferior izquierda del control.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(True)>
        <Category("Ejes Globales"), Description("Indica si se dibuja los ejes X-Y en la esquina inferior del control.")>
        Public Property EjesGlobales_Dibujar As Boolean
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _dibujarEjesControl
            End Get
            Set(value As Boolean)
                'Se actualiza el valor de la variable de la clase
                'con la que trabaja esta propiedad.
                _dibujarEjesControl = value
                'Actualizamos en el evento Paint, para que se vea reflejado el cambio de inmediato
                'cuando se está con el control en modo Diseño.
                Me.Refresh()
                '
            End Set
        End Property
        ''' <summary>
        ''' Indica si se desea dibujar los ejes X-Y en la parte inferior izquierda del control.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(True)>
        <Category("Ejes Globales"), Description("Indica el color de los ejes X-Y.")>
        Public Property EjesGlobales_Color As Color
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _dibujarEjesControl_Color
            End Get
            Set(value As Color)
                'Se actualiza el valor de la variable de la clase
                'con la que trabaja esta propiedad.
                _dibujarEjesControl_Color = value
                'Actualizamos en el evento Paint, para que se vea reflejado el cambio de inmediato
                'cuando se está con el control en modo Diseño.
                Me.Refresh()
                '
            End Set
        End Property
    
    #End Region
    
    #Region "Graphics de la Clase."
    
        ''' <summary>
        ''' Retorna el objeto Graphics del control proveniente del evento <seealso cref="Paint"/>  del control.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(False)>
        <Category("Graphics Control"), Description("Objeto Graphics proveniente del evento Paint del control.")>
        Public ReadOnly Property GraphicsControl_PaintEvent As Graphics
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _graphicsControl
            End Get
        End Property
    
        ''' <summary>
        ''' Retorna el zoom actual que se aplica al obejto <seealso cref="Graphics"/> del evento <seealso cref="Paint"/>  del control. Dicho valor
        ''' es actualizado con el evento <seealso cref="MouseWheel"/>  del control.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(False)>
        <Category("Graphics Control"), Description("Zoom actual que se aplica al ScaleTransform del Graphics del control.")>
        Public Property GraphicsControl_Zoom As Single
            Get
                'Se retorna el valor de la propiedad privada de la Clase.
                Return _zoom
            End Get
            Set(value As Single)
                _zoom = value
            End Set
        End Property
    
        ''' <summary>
        ''' Calidad con la que se dibujará los gráficos en el control.
        ''' </summary>
        ''' <returns></returns>
        <Browsable(True)>
        <Category("Graphics Control"), Description("Calidad con la qie se dibujará en el control.")>
        <DefaultValue(SmoothingMode.Default)>
        Public Property GraphicsControl_CalidadDibujo As SmoothingMode
            Get
                '
                'Retorna el valor de la variable de la propiedad.
                Return _graphicsControl_Quality
            End Get
            Set(value As SmoothingMode)
                'Se actualiza el valor de la variable de la clase
                'con la que trabaja esta propiedad.
                _graphicsControl_Quality = value
                '
            End Set
        End Property
    
        ''' <summary>
        ''' Color con el que se borrará el Graphics del control mediante el método <seealso cref="Graphics.Clear(Color)"/>
        ''' </summary>
        ''' <returns></returns>
        <Browsable(True)>
        <Category("Graphics Control"), Description("Color de borrado del Graphics del control.")>
        <DefaultValue(GetType(Color), "White")>
        Public Property GraphicsControl_ClearColor As Color
            Get
                '
                'Retorna el valor de la variable de la propiedad.
                Return _graphicsControl_ClearColor
            End Get
            Set(value As Color)
                'Se actualiza el valor de la variable de la clase
                'con la que trabaja esta propiedad.
                _graphicsControl_ClearColor = value
                '
            End Set
        End Property
    
    #End Region
    
    #End Region
    
    #Region "Constructor"
    
        ''' <summary>
        ''' Constructor predeterminado de la Clase.
        ''' </summary>
        Public Sub New()
    
            ' This call is required by the designer.
            InitializeComponent()
    
            'Se envía para que el control trabaje en DoubleBuffer.
            Me.DoubleBuffered = True
    
            'El control se le aplica la propiedad de DoubleBuffer, para reducir el parpadeo.
            SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
            SetStyle(ControlStyles.AllPaintingInWmPaint, True)
            SetStyle(ControlStyles.AllPaintingInWmPaint, True)
            '
            'Con el fin de hacer más fiable el código, se usa el método siguiente por medio de refleciones.
            SetDoubleBuffered(Me)
            '
            'El color por defecto del fondo del control será de color blanco, para que así
            'se muestre en tiempo de diseño por defecto del control.
            Me.BackColor = Color.White
            '
            'Se cambia el icono del cursor.
            Me.Cursor = Cursors.Cross
            '
            'Aplicamos BorderStyle al iniciar.
            Me.BorderStyle = BorderStyle.FixedSingle
    
        End Sub
    
        ''' <summary>
        ''' Convierte a DoubleBuffer un control, para reducir el parpadeo en el redibujado.
        ''' </summary>
        ''' <param name="c">Control de usuario donde se aplicará el DoubleBuffer.</param>
        Public Shared Sub SetDoubleBuffered(c As System.Windows.Forms.Control)
            'Taxes: Remote Desktop Connection and painting
            'http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx
            If System.Windows.Forms.SystemInformation.TerminalServerSession Then
                Return
            End If
            '
            'Se obtiene la propiead protegida de DoubleBuffer y se le aplica al control.
            Dim aProp As System.Reflection.PropertyInfo = GetType(Control).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance)
            'Envía el valor de la propiedad al control.
            aProp.SetValue(c, True, Nothing)
            '
        End Sub
    #End Region
    
    #Region "Eventos"
    
    #Region "Mouse control y Paint"
    
        ''' <summary>
        ''' Sobreescribe el evento Paint de la clase base del control.
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnPaint(e As PaintEventArgs)
            '
            'Asigno a la variable de la Clase el objeto Graphics obtenido.
            Me._graphicsControl = e.Graphics
            '
            'Borro con el color determinado el usuario el fondo del Graphics.
            Me._graphicsControl.Clear(GraphicsControl_ClearColor)
            '
            'Indico la calidad con lo que se dibujará los gráficos en el control. En caso de ser Invalid, coloco calidad
            'del dibujo en AntiAlis, para que no falle.
            Me._graphicsControl.SmoothingMode = If(Me.GraphicsControl_CalidadDibujo = SmoothingMode.Invalid, SmoothingMode.HighQuality, Me.GraphicsControl_CalidadDibujo)
    
            '
            'Verifico si el usuario ha decidio dibujar los ejes de referencia X-Y
            'en la esquina inferiir izquierda del control.
            If Me.EjesGlobales_Dibujar = True Then
                '
                'En este caso se desea es ajustar el Dibujo del Graphics al Control
                'con las dimensiones actuales del Control.
                'Llamo al evento de transformar el objeto Graphics con la altura actual que
                'se desea transformar.
                TransformarEjesGlobalesGraphics(Me._graphicsControl, Me.ClientRectangle.Height)
                '
                'Llamo al evento encargado de dibujar los ejes X-Y.
                Me.DibujarEjesControl()
                '
            End If
    
            '
            'Verifico si el usuario ha decidio dibujar las líneas de referencia del Mouse en el control.
            If Me.LineasReferenciaMouse_Dibujar = True Then
                '
                'Ajustamos los ejes coordenados del graphics con el actual control.
                TransformarEjesGlobalesGraphics(Me._graphicsControl, Me.ClientRectangle.Height)
                '
                'Aplicamos las escala de Zoom actual enviadas por el MouseWheel del control.
                Me._graphicsControl.ScaleTransform(Me._zoom, _zoom)
                '
                'Aplicamos la traslaciòn de los ejes coordenados de acuerdo a los eventos del Mouse del control.
                Me._graphicsControl.TranslateTransform(Me._TraslationX_Graphics, Me._TraslationY_Graphics)
                '
                'Llamo al mètodo encargado de dibujar las lìneas de referencia en la ubicaciòn actual
                'del Mouse.
                DibujarLineasReferenciaMouse(Me._mousePositionMove, Me._graphicsControl)
                '
            End If
    
    
            'Se crea una nueva instancia de la Clase de Zapata.
            Dim myzapata As New MyDrawings.ZapataPlanta(2, 2.5D, e.Graphics) With {
                .Contorno_Color = Color.Black,
                .Contorno_GrosorPen = 0.8D,
                .Relleno_Color = Color.Black,
                .Relleno_ColorTransparencia = 10
            }
    
            'Ontengo el Path que define mi dibujo.
            Dim myPath As GraphicsPath = myzapata.GraphicsPath_Dibujo
    
            'Obtengo todos los puntos que contienen el Path, el cual está con coordenadas del mundo.
            Dim myPointsAll_Path As PointF() = myPath.PathPoints
    
            'Centro del área de cliente o del control necesario para centrar el dibujo en pantalla.
            Dim centerControl As New PointF With {
                .X = (ClientRectangle.Left + ClientRectangle.Right) / 2.0F,
                .Y = (ClientRectangle.Bottom + ClientRectangle.Top) / 2.0F
            }
    
            'En este caso se desea es ajustar el Dibujo del Graphics al Control
            'con las dimensiones actuales del Control.
            'Llamo al evento de transformar el objeto Graphics con la altura actual que
            'se desea transformar.
            TransformarEjesGlobalesGraphics(Me._graphicsControl, Me.ClientRectangle.Height)
    
            'Primero verifico que el Dibujo que se quiera hacer en el Graphics
            'quiera ajustarse al tamaño actual del control y en el centro del mismo.
            If Me.IsFitDrawingToControl_ClikButtonEvent = True Then
    
                'Se transforma las coordenadas del Mundo, para lo cual el Graphics cuenta previamente con una matriz de Transformación
                'a coordenadas de la página, los puntos que contiene mi dibujo o Path a mostrar.
                _graphicsControl.TransformPoints(CoordinateSpace.Page, CoordinateSpace.World, myPointsAll_Path)
    
                'Centro del dibujo en el Eje X y Y, se obtiene con la suma de la mínima y máxima coordenada en el
                'eje, divido entre dos. Dichas coordenadas ya están convertidas a coordenadas de página.
                Dim centerDibujo As New PointF With {
                    .X = (myPointsAll_Path.Min(Function(x) x.X) + myPointsAll_Path.Max(Function(x) x.X)) / 2.0F,
                    .Y = (myPointsAll_Path.Min(Function(y) y.Y) + myPointsAll_Path.Max(Function(y) y.Y)) / 2.0F
                }
    
                'Hago coincidir el centro del dibujo con el (0,0) de las coordenadas de la página del control.
                _graphicsControl.TranslateTransform(-centerDibujo.X, -centerDibujo.Y, MatrixOrder.Append)
    
                'Obtengo el ratio para que el dibujo se ajuste al tamaño actual del control con ciertos márgenes(30).
                Dim scaleRatioPage As Single
                scaleRatioPage = Math.Min((ClientRectangle.Width - 60) / myPath.GetBounds.Width, (ClientRectangle.Height - 60) / myPath.GetBounds.Height)
    
                'Escalo el graphics para que el dibujo se amplie al tamaño actual del control.
                _graphicsControl.ScaleTransform(scaleRatioPage, scaleRatioPage, MatrixOrder.Append)
    
                'Por último hago coincidir el centro del dibujo con el centro del control.
                _graphicsControl.TranslateTransform(centerControl.X, centerControl.Y, MatrixOrder.Append)
    
    
                'Relleno y dibujo el Path deseado.
                _graphicsControl.FillPath(myzapata.Brush_RellenoZapata, myPath)
                _graphicsControl.DrawPath(myzapata.Pen_ContornoZapata(CDec(scaleRatioPage)), myPath)
    
    
                DibujarRegla(_graphicsControl, scaleRatioPage)
    
                '
                'Si el usuario está usando los eventos del Mouse, quiere decir
                'que está queriendo  hacer Zoom o Pan.
            ElseIf Me.IsZoomPan_MouseEvent = True Then
    
    
                'Si se desea que l dibujo se ajuste al área cliente, en esta parte del código debe aplicarse
                'el Scale Transform.
                Dim scaleRatioPage As Single
                scaleRatioPage = Math.Min((ClientRectangle.Width - 60) / myPath.GetBounds.Width, (ClientRectangle.Height - 60) / myPath.GetBounds.Height)
    
                'Se hace el traslado de acuerdo a la poción actual del Mouse y el Zoom del MouseWheel.
                Me._graphicsControl.TranslateTransform(Me._TraslationX_Graphics * (_zoom), Me._TraslationY_Graphics * (_zoom))
    
                'Se escala el Graphics para que se ajuste al dibujo.
                _graphicsControl.ScaleTransform(scaleRatioPage, scaleRatioPage)
                _graphicsControl.ScaleTransform(_zoom, _zoom)
    
                'Se dibuja el Path y se le aplica el relleno.
                _graphicsControl.FillPath(myzapata.Brush_RellenoZapata, myPath)
                _graphicsControl.DrawPath(myzapata.Pen_ContornoZapata(CDec(scaleRatioPage * _zoom)), myPath)
    
                'Se dibuja la regla con las coordenadas en el control.
                DibujarRegla(_graphicsControl, scaleRatioPage * _zoom)
    
            End If
    
            'CÓDIGO PARA VERIFICAR LA VERACIDAD DE LAS COORDENADAS CON EL MOUSEMOVE.
            Dim pointLoc(0) As PointF
            pointLoc(0) = _mousePositionMove
            _graphicsControl.TransformPoints(CoordinateSpace.World, CoordinateSpace.Device, pointLoc)
    
            Label1.Text = "X = " & CType(pointLoc(0).X, String)
            Label2.Text = "Y= " & CType(pointLoc(0).Y, String)
            '
            'Envoca el evento MouseDown del control.
            MyBase.OnPaint(e)
            '
        End Sub
    
        ''' <summary>
        ''' Sobreescribe el evento MouseDown de la clase base del control.
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
    
            'NOTA :Se produce cuando el puntero del mouse se encuentra sobre el control y se presiona un botón del mouse.
            'El orden de los eventos es :
            '
            'MouseEnter
            'MouseMove
            'MouseHover / MouseDown / MouseWheel
            'MouseUp
            'MouseLeave
    
            'Se verifica que ha presionado el botón izquierdo del Mouse.
            If e.Button = MouseButtons.Left Then
                '
                'Se verifica que no se tiene guardado en la variable antes un dato
                'que indica que se ha presionado el Mouse en el control.
                If Not Me._mouseDownPress = True Then
                    '
                    'Se presionò el botòn del mouse. 
                    Me._mouseDownPress = True
                    '
                    'Obtiene las coordenadas del puntero del Mouse cuando se presionó el Mouse.
                    Me._mouseDown_Location = e.Location
                    '
                    'Traslado previo que se ha hecho al Graphics, pues cuando se desea mover con el
                    'evento MouseMove o MouseWheel son los valores iniciales necesarios para poder
                    'actualizar de nuevo el Graphics a la posición actual que se desea.
                    Me._TraslationX_Graphics_old = Me._TraslationX_Graphics
                    Me._TraslationY_Graphics_old = Me._TraslationY_Graphics
                    '
                    'En este caso el dibujo sólo se está es ajustando con su Pan y Zoom.
                    IsZoomPan_MouseEvent = True
    
                    'Indico en False la variable que indica que se ajusta el dibujo
                    'a la pantalla actual.
                    IsFitDrawingToControl_ClikButtonEvent = False
    
                End If
                '
    
            End If
            '
            'Indico además que debe dibujarse las líneas de referencia del Mouse.
            LineasReferenciaMouse_Dibujar = True
            '        
            'Se redibuja el control en su evento Paint.
            Me.Refresh()
            '
            'Envoca el evento MouseDown del control.
            MyBase.OnMouseDown(e)
    
        End Sub
    
        ''' <summary>
        ''' Sobreescribe el evento MouseMove de la clase base del control.
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
            '
            'Se obtiene la posición actual del Mouse.
            Me._mousePositionMove = e.Location
    
            'Se verifica que ha presionado el botón izquierdo del Mouse.
            If e.Button = MouseButtons.Left Then
                '
                'Se cambia el icono del cursor.
                'Dim ms As MemoryStream = New MemoryStream(My.Resources.hold_1)
                Me.Cursor = Cursors.SizeAll
                '
                'Posición actual del puntero del mouse.
                Dim mousePosNow As PointF = e.Location
                '
                'Variable para saber cuanto debe desplazarse el objeto gráfico de acuerdo a la 
                'posición guardada en el evento MouseDown y la actual en este evento.
                Dim deltaX, deltaY As Single
                'Se halla los valores de desplazamiento.
                deltaX = mousePosNow.X - Me._mouseDown_Location.X
                '
                'Dado que el sentido del Eje Y del Graphics ha cambiado, se multiplica el delta de desplazamiento por -1, para
                'que no falle el Pan y Move. Debe entonces usarse una transformaciòn del Graphics de la Clase, para que el 
                'origen del Graphics sea en la parte inferior izquierda del control y con valores positivos hacia arriba.
                deltaY = (mousePosNow.Y - Me._mouseDown_Location.Y) * -1
                '
                'Se obtiene DE NUEVO el desplazamiento que debe realizarse en el Objeto Graphics, teniendo en cuenta
                'el valor pasado de dichos traslados obtenidos en el el evento MouseDown+ el nuevo delta de desplazamiento
                'teniendo en cuenta de dividir dicho valor con el valor actual del zoom.
                Me._TraslationX_Graphics = (Me._TraslationX_Graphics_old + (deltaX / Me._zoom))
                Me._TraslationY_Graphics = (Me._TraslationY_Graphics_old + (deltaY / Me._zoom))
                '
                'En este caso el dibujo sólo se está es ajustando con su Pan y Zoom.
                IsZoomPan_MouseEvent = True
                '
                'Indico en False la variable que indica que se ajusta el dibujo
                'a la pantalla actual.
                IsFitDrawingToControl_ClikButtonEvent = False
                '
    
            End If
            '
            'Indico además que debe dibujarse las líneas de referencia del Mouse.
            LineasReferenciaMouse_Dibujar = True
    
            'Se redibuja el control en su evento Paint.
            Me.Refresh()
            '
            'Envoca el evento MouseMove del control.
            MyBase.OnMouseMove(e)
    
        End Sub
    
        ''' <summary>
        ''' Se produce cuando el puntero del mouse se encuentra sobre el control y se suelta un botón del mouse.
        ''' Sobreescribe el evento MouseMove de la clase base del control.
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnMouseUp(e As MouseEventArgs)
            '
            'Este evento ocurre cuando el puntero del Mouse se encuentra sobre el control
            'y soltó un botón del Mouse.
            '
            'Se indica que ya no se encuentra presionado el botón del Mouse.
            Me._mouseDownPress = False
    
            'Se cambia el icono del cursor, cuando se suelta el botón del mouse que actualmente se presionaba.
            Me.Cursor = Cursors.Cross
            '
            'Envoca el evento MouseUp del control.
            MyBase.OnMouseUp(e)
    
        End Sub
    
        ''' <summary>
        ''' Se produce cuando la rueda del mouse se mueve mientras el control tiene el foco.
        ''' Sobreescribe el evento MouseMove de la clase base del control.
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnMouseWheel(e As MouseEventArgs)
            '
            'Actualizo el valor del zoom actual, antes de que se calcule el nuevo en este evento.
            Me._zoom_old = Me._zoom
    
            'Hacemos que se vuelva a redibujar, para que se pueda mostrar la grilla.
            'Me.Refresh()
    
            'Verifico que el paso de la muesca del mouse se hace hacia arriba.(>zoom).
            If e.Delta > 0 Then
                '
                'Se incrementa el zoom, de acuerdo a la variable constante de la clase. Se
                'tiene en cuenta que no se sobrepase del mayor valor del zoom. El màximo valor 
                'del zoom es una Constante llamada _zoom_max.
                Me._zoom = Math.Min((Me._zoom + _zoom_increment), _zoom_max)
    
                'De otro modo, se está haciendo un zoom de alejamiento.
            Else
                '
                'Para el caso de disminución del Mouse, establezco un mínimo valor para no tener 
                'problemas de OverFlow. El mínimo valor del zoom es uua Constante llamada _zoom_min.
                Me._zoom = Math.Max((Me._zoom - _zoom_increment), _zoom_min)
    
            End If
            '
            'Se obtiene la posición actual del Mouse actual.
            Dim mousePosNow As PointF = e.Location
            '
            'Variables para saber el valor de los deltas entre la posición actual del mouse
            'y la ubicación de la parte superior izquierda del PictureBox.
            Dim deltaX, deltaY As Single
            deltaX = mousePosNow.X - 0
            '
            'Dado que el origen de coordenadas del Graphics del control ha cambiado a la parte
            'inferior izquierda del Mouse y con valores positivos del Eje Y hacia arriba, se 
            'resta del valor actual del Heigth la posiciòn actual del Mouse.
            deltaY = Me.ClientRectangle.Height - mousePosNow.Y
            '
            'Variable que guardan el valor teniendo en cuenta el zoom inmediatamente
            'anterior de los desplazamientos que sufrió el Graphics.
            Dim oldGraphicsX As Single
            Dim oldGraphicsY As Single
            oldGraphicsX = ((deltaX / Me._zoom_old))
            oldGraphicsY = ((deltaY / Me._zoom_old))
            '
            'Variable para guardar los nuevos desplazamientos que debe sufrir el Graphics,
            'para que el centro del foco del Zoom sea la ubicación actual del Mouse.
            Dim newGraphicsX As Single
            Dim newGraphicsY As Single
            newGraphicsX = ((deltaX / Me._zoom))
            newGraphicsY = ((deltaY / Me._zoom))
            '
            'Los nuevos valores de Traslado del objeto Graphics se obtiene.
            Me._TraslationX_Graphics = newGraphicsX - oldGraphicsX + Me._TraslationX_Graphics
            Me._TraslationY_Graphics = newGraphicsY - oldGraphicsY + Me._TraslationY_Graphics
    
            '
            'En este caso el dibujo sólo se está es ajustando con su Pan y Zoom.
            IsZoomPan_MouseEvent = True
            '
            'Indico además que debe dibujarse las líneas de referencia del Mouse.
            LineasReferenciaMouse_Dibujar = True
    
            'Indico en False la variable que indica que se ajusta el dibujo
            'a la pantalla actual.
            IsFitDrawingToControl_ClikButtonEvent = False
    
            'Se redibuja el control en su evento Paint.
            Me.Refresh()
            '
            'Envoca el evento MouseWheel del control.
            MyBase.OnMouseWheel(e)
    
        End Sub
    
        ''' <summary>
        ''' Se produce cuando el puntero del Mouse sale del control.
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnMouseLeave(e As EventArgs)
            '
            'En este caso las líneas de referencia del Mouse, ya no deben dibujarse, por tal motivo
            'indico a la variable de la Clase que no se está haciendo efectos de Zoom o Pan.
            '
            'En este caso las líneas del Mouse no deben dibujarse.
            Me.LineasReferenciaMouse_Dibujar = False
            '
            'Se redibuja el control en su evento Paint.
            Me.Refresh()
            '
            'Envoca el evento MouseLeave del control.
            MyBase.OnMouseLeave(e)
            '
        End Sub
    
    #End Region
    
    #Region "Menu contextual control"
    
        ''' <summary>
        ''' Se produce cuando presiona la opción de mover del menu contextual del control.
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Private Sub CmsOpt_Mover_Click(sender As Object, e As EventArgs) Handles CmsOpt_Mover.Click
    
            'Se cambia el icono del cursor.
            'Dim ms As MemoryStream = New MemoryStream(My.Resources.hold_1)
            Me.Cursor = Cursors.SizeAll
    
            'Redibujamos el control.
            Me.Invalidate()
    
        End Sub
    
        ''' <summary>
        ''' Se produce cuanse se ha presionado la opción de Ajustar el dibujo al tamaño actual del control
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Private Sub CmsOpt_Ajustar_Click(sender As Object, e As EventArgs) Handles CmsOpt_Ajustar.Click
            '
            'De nuevo coloco en False la variable que indica que se ajusta el dibujo
            'a la pantalla actual.
            IsFitDrawingToControl_ClikButtonEvent = True
            '
            'Activamos el Zoom y Pan del control, para que se muestre las 
            'lineas de referencia y pueda hacer funciones de Zoom y Pan
            'de una vez al entrar el Mouse al control.
            IsZoomPan_MouseEvent = False
    
            'Restauramos del control los valores de Traslación y Zoom
            'para que no falle cuando luego de este evento se vuelva pasar
            'el mouse por el control.
            RestaurarZoomTraslate_Graphics()
            '
            'Obligo a redibujar el dibujo ajustado a la pantalla.
            Refresh()
    
        End Sub
    
        ''' <summary>
        ''' Se produce cuando se presiona la opción de Aumentar el Zoom del control desde el menu contextual del mismo.
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Private Sub CmsOpt_Ampliar_Click(sender As Object, e As EventArgs) Handles CmsOpt_Ampliar.Click
    
            'Aumento el Zoom actual del control, la constante definida de aumento o disminución.
            _zoom += _zoom_increment
    
            'En este caso el dibujo sólo se está es ajustando con su Pan y Zoom.
            IsZoomPan_MouseEvent = True
            '
            'Indico además que debe dibujarse las líneas de referencia del Mouse.
            LineasReferenciaMouse_Dibujar = True
            '
            'En este caso el dibujo sólo se está es ajustando con su Pan y Zoom,
            'más no debe ajustarse al tamaño del Form.
            IsFitDrawingToControl_ClikButtonEvent = False
    
            'Redibujamos el control.
            Me.Refresh()
    
        End Sub
    
        ''' <summary>
        ''' Se produce cuando se presiona la opción de Disminuir el Zoom del control desde el menu contextual del mismo.
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Private Sub CmsOpt_Reducir_Click(sender As Object, e As EventArgs) Handles CmsOpt_Reducir.Click
    
            'Disminuyo el Zoom actual del control, la constante definida de aumento o disminución.
            _zoom -= _zoom_increment
    
            'En este caso el dibujo sólo se está es ajustando con su Pan y Zoom.
            IsZoomPan_MouseEvent = True
            '
            'Indico además que debe dibujarse las líneas de referencia del Mouse.
            LineasReferenciaMouse_Dibujar = True
            '
            'En este caso el dibujo sólo se está es ajustando con su Pan y Zoom,
            'más no debe ajustarse al tamaño del Form.
            IsFitDrawingToControl_ClikButtonEvent = False
            '
            'Redibujamos el control.
            Me.Refresh()
    
        End Sub
    
    #End Region
    
    #End Region
    
    #Region "Mètodos"
    
        ''' <summary>
        ''' Permite dibujar una regla parab cada uno de los Ejes, con el fin de mostrar las coordenadas de ubicación.
        ''' </summary>
        ''' <param name="g">Graphics del control donde se dibujará.</param>
        ''' <param name="theScale">Escala actual que se le aplica al Graphics con el fin de podes dibujar la regla y el tamaño
        ''' del texto ajustado.</param>
        Private Sub DibujarRegla(g As Graphics, theScale As Single)
    
            'VARIABLE GENERALES.
            '------------------
            '
            'Pen con el que se dibujará la línea de la regla.
            Dim pen_regla As Pen = New Pen(Color.DarkBlue, 0)
            '
            'Color con el que se pintará el texto de la regla.
            Dim sb_texto As SolidBrush = New SolidBrush(Color.DarkRed)
    
            For x = 0 To g.VisibleClipBounds.Right Step 1
    
                ' GraphocsPath para dibujar el texto de la coordenada del Eje X.
                Dim pathTexto_AxisX As New GraphicsPath
                '
                'Parámetros para dibujar el Texto.
                '-----
                '
                'Texto que se mostrará.
                Dim stringText As String = FormatNumber(x, 2, TriState.True, TriState.False)
                '
                'Fuente del texto.
                Dim family As New FontFamily("Consolas")
                '
                'Altura del texto en MM convertido a pixeles teniendo en cuenta la escala actual del Graphics.
                Dim altTexto As Single = Conversion_MM_Pix(2.5D) / theScale
                '
                'Origen donde empezará a dibujarse el Texto. En este caso, se ubica en donde está la coordeanada
                'a dibujar en el Eje X, y en el Eje Y  en la parte inferior de la coordenada visible del Graphics
                'desfasado 10 Pix hacia arriba. La línea de la regla también debe medir esos 10 Pix, para que el 
                'texto se óbserve correctamente.
                Dim origin As New PointF(x, -g.VisibleClipBounds.Top - (10 / theScale))
                '
                'Formato para el texto que se dibujará con el fin de darle ciertas propiedades.
                Dim format As StringFormat = StringFormat.GenericTypographic
                '
                'Se aplica caracterísiticas al Formato del Texto.(*)
                With format
                    'Se muestra el texto de la forma tradiciona de izquierda a derecha.
                    .FormatFlags = StringFormatFlags.DisplayFormatControl
                    'Horizontalmente, el texto se muestra centrado de acuerdo a su posición.
                    .Alignment = StringAlignment.Center
                    'Verticalmente el Texto se muestra en su posición más lejana posible.
                    .LineAlignment = StringAlignment.Far
                    '
                End With
                '(*)
                '
                'Se adiciona el texto que representa la coordenada al Path.
                pathTexto_AxisX.AddString(stringText, family, FontStyle.Bold, altTexto, origin, format)
                '
                'Se le aplica al Path la misma transformada del Graphics, que es hacer que el Eje y apunta hacia arriba.
                Dim mt As New Matrix(1, 0, 0, -1, 0, 0)
                pathTexto_AxisX.Transform(mt)
                '
                'Se dibuja la línea que representa la Regla.
                g.DrawLine(pen_regla, x, g.VisibleClipBounds.Y, x, g.VisibleClipBounds.Y + (10 / theScale))
                '
                'Se dibuja el texto, para lo cual se hace uso del relleno del texto.
                g.FillPath(sb_texto, pathTexto_AxisX)
                '
            Next
    
            For y = 0 To g.VisibleClipBounds.Bottom Step 1
    
                ' Create a GraphicsPath object.
                Dim pathTexto_AxisY As New GraphicsPath
    
                '' Set up all the string parameters.
                Dim stringText As String = FormatNumber(y, 2, TriState.True, TriState.False)
                Dim family As New FontFamily("Consolas")
                Dim altTexto As Single = Conversion_MM_Pix(2.5D) / theScale
                Dim origin As New PointF(g.VisibleClipBounds.Left + (10 / theScale), 0)
                Dim format As StringFormat = StringFormat.GenericTypographic
                format.FormatFlags = StringFormatFlags.DirectionVertical
                format.Alignment = StringAlignment.Center
                format.LineAlignment = StringAlignment.Far
    
                ' Add the string to the path.
    
                pathTexto_AxisY.AddString(stringText, family, FontStyle.Bold, altTexto, origin, format)
    
                Dim mt As New Matrix(1, 0, 0, -1, 0, 0)
                mt.Translate(0, -y)
                mt.RotateAt(180, origin)
                pathTexto_AxisY.Transform(mt)
    
                'x axis
                g.DrawLine(pen_regla, g.VisibleClipBounds.Left, y, g.VisibleClipBounds.Left + (10 / theScale), y)
    
                'x axis
                g.FillPath(sb_texto, pathTexto_AxisY)
    
            Next
            '
            'Se liberan recursos.
            pen_regla.Dispose()
            sb_texto.Dispose()
    
        End Sub
    
    
        ''' <summary>
        ''' Dibuja las lìneas de referencia horizontal y vertical en la posición actual del Mouse,
        ''' mientras se mueve por el control. Esto siempre y cuando la propiedad <seealso cref="IsZoomPan_MouseEvent"/>
        ''' sea <seealso cref="vbTrue"/>
        ''' </summary>
        ''' <param name="positionMouse"></param>
        ''' <param name="graphics"></param>
        Private Sub DibujarLineasReferenciaMouse(positionMouse As PointF, graphics As Graphics)
            '
            'Se crea un nuevo pincel de dibujo con el color especificado en las propeidades
            'de la Clase.
            '
            'Se asigna un ancho del pixel en mm de las lìneas de referencia. Siempre
            'debe de tenerse en cuenta el Zoom actual del Graphics, para que siempre salga
            'con el mismo valor del Ancho. Lo que se hace es convertir el valor de los MM a pixeles, teniendo en cuenta
            'la resolución del equipo y el zoom actual.
            '
            Dim pencil As New Pen(Me._LineasReferenciaMouse_Color) With {
                .Width = ((Me._LineasReferenciaMouse_GrosorMM) * (graphics.DpiX) * (1 / 25.4F)) / Me._zoom
            }
            '
            'ESTILO DE LÍNEA QUE SE DIBUJARÁ
            '----------
            '---------
            '
            If Me._LineasReferenciaMouse_TipoLinea = LineaReferenciaMouse_Tipo.Continua Then
                '
                'Se asigna el tipo de línea sólida.
                pencil.DashStyle = Drawing2D.DashStyle.Solid
                '
            ElseIf Me._LineasReferenciaMouse_TipoLinea = LineaReferenciaMouse_Tipo.Discontinua Then
                '
                'Tramo de línea que se dibuja y espacio entre ellas.
                Dim tramosLinea() As Single = {Conversion_MM_Pix(4), Conversion_MM_Pix(2)}
                '
                'Se asigna el tipo de línea.
                pencil.DashPattern = tramosLinea
                '
                'Se indica que es personalizada el tipo de línea.
                pencil.DashStyle = DashStyle.Custom
                '
            End If
            '
            'TERMINA ESTILO DE LÍNEA QUE SE DIBUJARÁ.
            '------------
            '------------
    
            'Se obtiene el ancho y alto visible del Graphics actual.
            Dim width As Single = graphics.ClipBounds.Width
            Dim heigth As Single = graphics.ClipBounds.Height
    
            'Se dibuja la linea vertical
            graphics.DrawLine(pencil, (positionMouse.X) / Me._zoom - Me._TraslationX_Graphics, -Me._TraslationY_Graphics, (positionMouse.X) / Me._zoom - Me._TraslationX_Graphics, heigth - Me._TraslationY_Graphics)
            'Se dibuja la linea HORIZONTAL
            graphics.DrawLine(pencil, -Me._TraslationX_Graphics, heigth - positionMouse.Y / Me._zoom - Me._TraslationY_Graphics, width - Me._TraslationX_Graphics, heigth - positionMouse.Y / Me._zoom - Me._TraslationY_Graphics)
            '
            'Se liberan recursos.
            pencil.Dispose()
    
        End Sub
    
    #Region "Dibujar ejes globales"
    
        ''' <summary>
        ''' Dibuja los ejes X-Y en la parte inferior izquierda del control.
        ''' </summary>
        Private Sub DibujarEjesControl()
            '
            'Calidad con la que se dibuja los textos.
            'Me.GraphicsControl_PaintEvent.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
            '
            'Indica la longitud en pixeles para las líneas de los ejes X y Y.
            Dim largoLineasEjes As Single = 50.0F
            'Coordenada que indica el punto inicial medido desde la parte inferior izquierda
            'del control que empezará los ejes X y Y.
            Dim posInicialEjes As New PointF(10, 10)
            '
            'Se crea un nuevo pincel de dibujo con el color especificado en las propeidades
            'de la Clase.
            'Se coloca valor en mm del grosor de las líenas del Eje. Siempre serán de 0.10 mm.
            'El tipo de lìnea es solida y con redondeo al final de las mismas.
            Dim pencil As New Pen(Me.EjesGlobales_Color) With {
                .Width = ((0.1F) * (Me.GraphicsControl_PaintEvent.DpiX) * (1 / 25.4F)),
                .LineJoin = LineJoin.Round,
                .DashStyle = Drawing2D.DashStyle.Solid
            }
    
            'Se crea un Path para dibujar el CustomLineCap del pencil. Con esto garantizo dibujar
            'algo parecido a los ejes de SAP2000.
            Dim ejesPathCap As New GraphicsPath(FillMode.Winding)
            '
            'Se crea una nube de puntos para personalizar la flecha de los ejes X y Y.
            Dim pointsEndCap() As PointF = New PointF() {New PointF(0, 0), New PointF(6, -10), New PointF(0, 10),
                 New PointF(-6, -10), New PointF(0, 0)}
            'Se adiciona un Polígono que formará la flecha de los ejes.
            ejesPathCap.AddPolygon(pointsEndCap)
            'Adicionamos los Textos para mostrar los ejes X y Y.
            '
            'Creo un nuevo CustomLineCap, para que al EndCap del Pencil del dibujo
            'se dibuje el Path creadp.
            Dim customCap As New CustomLineCap(Nothing, ejesPathCap)
            'Adiciono al Pincel el CustomEndCap para que dibuje una flecha al finalizar las líneas
            'que se dibujen con ese pincel.
            pencil.CustomEndCap = customCap
            '
            'Punto para dibujar eje X.
            Dim ejeY() As PointF = New PointF() {New PointF(posInicialEjes.X, posInicialEjes.Y), New PointF(largoLineasEjes, posInicialEjes.Y)}
            '   '
            'Punto para dibujar eje Y
            Dim ejeX() As PointF = New PointF() {New PointF(posInicialEjes.X, posInicialEjes.Y), New PointF(posInicialEjes.X, largoLineasEjes)}
            '
            'Dibujo las líneas en el Graphics con el tipo de Pincel creado.
            Me.GraphicsControl_PaintEvent.DrawLines(pencil, ejeY)
            Me.GraphicsControl_PaintEvent.DrawLines(pencil, ejeX)
            '
            'Creamos la fuente con la que se dibujará el "X" y el "Y"
            Dim miLetrasEjes As New Font("Consolas", 2.8, FontStyle.Bold, GraphicsUnit.Millimeter)
    
            'En este caso el Texto se dibuja teniendo en cuenta que el Graphics está en la parte superior
            'izquierda del control, con el fin de que no tender un texto invertido si se sigue trabajando
            'con la TransformadaGlobal del Graphics.
            '
            'Se crea alineación del texto a dibujar.
            Dim alinear_texto As StringFormat = StringFormat.GenericDefault
    
            With alinear_texto
                .Alignment = StringAlignment.Center
                .LineAlignment = StringAlignment.Center
            End With
    
    
            Dim sizeX, sizeY As New SizeF
            'Obtenemos el tamaño de los textos que se dibujan.
            sizeX = Me.GraphicsControl_PaintEvent.MeasureString(Me.EjesGlobales_LetraEjeHorizontal, miLetrasEjes)
            sizeY = Me.GraphicsControl_PaintEvent.MeasureString(Me.EjesGlobales_LetraEjeVertical, miLetrasEjes)
    
            'Indicamos la posición en la que se dibujará el texto
            Dim ejeY_Point As New PointF(posInicialEjes.X, Me.ClientRectangle.Height - posInicialEjes.Y - largoLineasEjes - 2)
            Dim ejeX_Point As New PointF(posInicialEjes.X + largoLineasEjes, Me.ClientRectangle.Height - posInicialEjes.Y)
            '
            'Reseteo la transfomrada Global del Graphics, para poder trabajar con el origen de coordenadas
            'convencional del Graphics, ubicado en la parte superior Izquierda del Control, y de esta forma
            'poder dibujar el Textp de forma correcta.
            Me.GraphicsControl_PaintEvent.ResetTransform()
            '
            'Dibujo el texto para los ejes X y Y.
            Me.GraphicsControl_PaintEvent.DrawString(Me.EjesGlobales_LetraEjeHorizontal, miLetrasEjes, pencil.Brush, ejeX_Point, alinear_texto) 'Eje Horizontal.
            Me.GraphicsControl_PaintEvent.DrawString(Me.EjesGlobales_LetraEjeVertical, miLetrasEjes, pencil.Brush, ejeY_Point, alinear_texto) 'Eje Vertical.
            '
            'Se liberan recursos.
            ejesPathCap.Dispose()
            customCap.Dispose()
            pencil.Dispose()
    
        End Sub
    
    #End Region
    
        ''' <summary>
        ''' Transforma los ejes globales del control, ubicándolos en la parte inferior izquierda del control, y con los 
        ''' sentidos positivos de cada uno de los ejes hacia la derecha(X) y hacia arriba(Y).
        ''' </summary>
        ''' <param name="gra"></param>
        ''' <param name="altoControl"></param>
        Private Sub TransformarEjesGlobalesGraphics(gra As Graphics, altoControl As Integer)
            '
            'Dado que se está volviendo a pintar debe de nuevo aplicarse la matrix de transformación
            'Global del Graphics, para que el eje coordenado quede ubicado en la parte inferior izqquierda del control.
            'Cambia la orientación del eje coordenado Y hacia arriba(positivo) y hacia la derecha positivo.
            Dim mtxTransform As Matrix = New Matrix(1, 0, 0, -1, 0, 0)
            'Al Graphics del PictureBox se le envía dicha transformación.
    
            'Se asigna la transformada al Graphics.
            gra.Transform = mtxTransform
    
            'Ahora para que el origen(0,0) quede en la parte inferior izquierda del PictureBox
            'se traslada una distancia negativa(hacia abajo) la altura del Picturebox, previo al
            'cambio del tamaño del Form.
            gra.TranslateTransform(0, -altoControl)
            mtxTransform.Dispose()
    
        End Sub
    
        'Método llamado para restaurar el valor de las propiedades de Zoom y TraslateGraphics del control. Esto
        'es necesario cuando se ajusta el dibujo en el Graphics en toda la pantalla, por medio de un Button en su
        'evento click. Con esto se evita fallos al volver de nuevo a entrar en el control, pues de no ser asì,
        'al ajustarse el dibujo y luego al querer entrar con el Mouse por el control se redibuja con valores antiguos
        'del Zoom.
        Public Sub RestaurarZoomTraslate_Graphics()
            '
            'Restauro por defecto las varaibles con las que se hace uso los eventos de Zoom y Pan.
            Me._TraslationX_Graphics = 0
            Me._TraslationY_Graphics = 0
            Me._TraslationX_Graphics_old = 0
            Me._TraslationY_Graphics_old = 0
            Me._zoom = 1
            Me._zoom_old = 1
            '
        End Sub
    
        Private Sub ModelControl_Resize(sender As Object, e As EventArgs) Handles Me.Resize
            '
            'Refrescamos siempre el dibujo al entrar en modo Resize el Control.
            Me.Refresh()
            '
        End Sub
    
    
    #End Region
    
    #Region "Enumeradores"
    
    #Region "Líneas de referencia del Mouse"
    
        ''' <summary>
        ''' Tipo de línea que se mostrará cuando se muestre las líneas de referencia del mouse en el control.
        ''' </summary>
        <Flags>
        Public Enum LineaReferenciaMouse_Tipo As Integer
    
            ''' <summary>
            ''' Línea continua sólida.
            ''' </summary>
            Continua = 0
            ''' <summary>
            ''' Línea discontinua punteada.
            ''' </summary>
            Discontinua = 1
            '
        End Enum
    
    
    
    #End Region
    
    #End Region
    
    #Region "Utilidades"
    
        ''' <summary>
        ''' Convierte un valor en Milímetros a Pixeles.
        ''' </summary>
        ''' <param name="valueMM"></param>
        ''' <returns></returns>
        Private Function Conversion_MM_Pix(valueMM As Decimal) As Decimal
            '
            'Variable con el valor de la convesión.
            Dim valorConvertido As Decimal
            '
            'Conversión:
            valorConvertido = CDec((valueMM) * _graphicsControl.DpiX * (1 / 25.4D))
            '
            'Se retorna el valor convertido.
            Return valorConvertido
            '
        End Function
    
    
    #End Region
    
    End Class

    Por favor, agradezco que alguien pueda brindarme la mano.

    Dios le bendiga.


    Harold Alonso Quintero Pineda Ingeniero Civil Universidad Francisco de Paula Santander Ocaña Correo: haroldpineda1401@outlook.com Cel: 3158700970


    sábado, 17 de febrero de 2018 13:42