Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Harold23

#1
Hola, muy buenas tardes;

Estoy intentando crear un control personalizado en VS2017, que me permita mostrar una regla en los bordes superior e izquierdo con marcas de texto, basado en un sustema de unidades, sea milímetros o metros. He empeza tratando de crear los efectos ZOOM y PAN, dibujando un rectángulo de ejemplo, y funciona bien.

Mi idea es obtener esto(obvien el rectángulo, que lo dibujé para probar el ZOOM y PAN, pero si las líneas de referencia del cursor):



Para ello en VS he creado un proyecto de tipo UserControl, y el código que he usado es el siguiente:

Código (vbnet) [Seleccionar]
''' <summary>
''' Control personalizado para mostrar gráficos vectoriales.
''' </summary>
Public Class Canvas

    Inherits System.Windows.Forms.UserControl

#Region "Constructor"

    ''' <summary>
    ''' Constructor predeterminado del control de usuario.
    ''' </summary>
    Public Sub New()

        ' Esta llamada es exigida por el diseñador.
        InitializeComponent()

        ' Agregue cualquier inicialización después de la llamada a InitializeComponent().

        'Se asigna ciertas propiedades de inicio para el control.
        '---------

        'El control se mostrará acoplado al panel donde se desee insertar.
        Me.Dock = DockStyle.None
        'Dado que es un control para dibujar, se adiciona la propiedad de DoubleBuffer para reducir el parpadeo.
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(ControlStyles.UserPaint, True)
        Me.Cursor = Cursors.Cross
    End Sub

#End Region

#Region "Variables"
    ''' <summary>
    ''' Verifica si un botón del Mouse se ha presionado dentro de un control.
    ''' </summary>
    Private _mousePress 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 PointF
    ''' <summary>
    ''' Posición actual del mouse cuando se activa el evento MouseMove.
    ''' </summary>
    Private _mousePositionMove As PointF
    Private _TraslationX_Graphics_old As Single = 0F
    Private _TraslationY_Graphics_old As Single = 0F
    ''' <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 = 0F
    ''' <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 = 0F
    ''' <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 "Eventos"

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        MyBase.OnPaint(e)

        Dim g As Graphics = e.Graphics

        'Envío el objeto Graphics, para que dibuje teniendo en cuenta las transformaciones.
        TransformarGraphics(g)
        DrawLineReferencieMouse(Me._mousePositionMove, g)

    End Sub

    Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
        MyBase.OnMouseDown(e)
        '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 verifica que no se tiene g
            If Not Me._mousePress = True Then

                Me._mousePress = True
                '
                'Obtiene las coordenadas del puntero del Mouse cuando se presionó el Mouse.
                Me._mouseDown_Location = e.Location
                Me._TraslationX_Graphics_old = Me._TraslationX_Graphics
                Me._TraslationY_Graphics_old = Me._TraslationY_Graphics
            End If

            Me.Invalidate(False)

        End If

    End Sub

    Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
        MyBase.OnMouseMove(e)

        '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 = New Cursor(ms)
            '
            '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 haya los valores de desplazamiento.
            deltaX = mousePosNow.X - Me._mouseDown_Location.X
            deltaY = mousePosNow.Y - Me._mouseDown_Location.Y
            '
            '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))
            '
            '
            'Obligo a redibujar el control.
            Me.Invalidate(False)

        End If

    End Sub


    Protected Overrides Sub OnMouseUp(e As MouseEventArgs)
        MyBase.OnMouseUp(e)
        '
        '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._mousePress = False
        'Se cambia el icono del cursor, cuando se suelta el botón del mouse que actualmente se presionaba.
        Me.Cursor = Cursors.Cross
        Me.Invalidate(False)
    End Sub

    Protected Overrides Sub OnMouseWheel(e As MouseEventArgs)

        MyBase.OnMouseWheel(e)
        '
        'Actualizo el valor del zoom actual, antes de que se calcule el nuevo en este evento.
        Me._zoom_old = Me._zoom

        '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.
            Me._zoom = Math.Min(Me._zoom + _zoom_increment, _zoom_max)
        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
            Me._zoom = Math.Max(Me._zoom - _zoom_increment, _zoom_min)
        End If
        '
        'Se obtiene la posición actual del Mouse.
        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 - Me.Location.X
        deltaY = mousePosNow.Y - Me.Location.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

        'Se obtiene la posición actual del Mouse.
        Me._mousePositionMove = mousePosNow

        'Se obliga a redibujar el control.
        Me.Invalidate(False)

    End Sub

#End Region

#Region "Métodos"

    ''' <summary>
    ''' Realiza las transformaciones del Canvas, en este un escalamiento(zoom) y un traslado
    ''' de coordendas para que el zoom sea respecto a una posición en específica.
    ''' </summary>
    ''' <param name="canvas"></param>
    Private Sub TransformarGraphics(canvas As Graphics)

        'Borramos la superficie de dibujo y aplicacmos un color de fondo.
        canvas.Clear(Color.Black)
        'Suavizado de los pixeles para disminuir el parpadeo al redibujar.
        'canvas.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
        'canvas.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
        canvas.SmoothingMode = Drawing2D.SmoothingMode.HighSpeed
        '
        'Se aplica el escalado actual del onjeto gráfico. Este valor se ajusta en el evento MouseWheel del Control de dibujado.
        canvas.ScaleTransform(Me._zoom, Me._zoom)
        '
        'Se traslada el origen de las coordenadas, para que el centro del zoom coincida
        'con la posición del mouse actual.
        canvas.TranslateTransform(Me._TraslationX_Graphics, _TraslationY_Graphics)
        '
        'Pindel para dibujado de los objetos.
        Dim pen As New Pen(Color.Red)
        'Establezco un ancho de la línea siempre de 1.5 pix, sin importar el zoom.
        pen.Width = 1.0F / Me._zoom
        'Patrón del tipo de línea a usar del Pen, con 20 pix de línea espaciadas cada 10 pix.
        Dim tipo_linea() As Single = {20, 10}
        'Asigno el tipo de línea personalizada.
        pen.DashStyle = Drawing2D.DashStyle.Custom
        'Asigno el tipo de línea.
        pen.DashPattern = tipo_linea
        pen.LineJoin = Drawing2D.LineJoin.Bevel
        'Dibuja un rectángulo de ejemplo para probar ZOOM y PAN.
        canvas.DrawRectangle(pen, 100, 150, 500, 400)

        Me.Invalidate(False)

    End Sub

    Private Sub DrawLineReferencieMouse(positionMouse As PointF, graphics As Graphics)

        graphics.PageUnit = GraphicsUnit.Pixel

        Dim pencil As New Pen(Color.White)
        Dim tipolinea As Single() = New Single() {10, 15}
        pencil.Width = 1 / Me._zoom
        pencil.ScaleTransform(Me._zoom, Me._zoom)

        pencil.DashPattern = tipolinea
        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, positionMouse.Y / Me._zoom - Me._TraslationY_Graphics, width - Me._TraslationX_Graphics, positionMouse.Y / Me._zoom - Me._TraslationY_Graphics)

        Me.Invalidate(False)

    End Sub

#End Region
End Class


El problema es que cuando INTENTO correr el control personalizado en el proyecto de creación, no me muestra las propiedades a mano derecha y empieza a parpadear. Sé que esto pasa por el evento Paint, pero pues no se conceptualmente como solucionarlo.



De igual forma pasa, cuando intento usar el control en un proyecto de prueba, al agregarlo en el Form, se observa que parpadea, y cuando intento correr el Test, ni si quiera arranca.



Podrían ayudarme a solucionar esto. Mi idea es crea posteriormente un control para dibujar con GDI+ con sobre él, y quiero es mostrar unas reglas en dicho control en unidades varias, hacer el zoom y el pan, éstos dos últimos que ya funcionan en el ejemplo que acabé de pasar.

¿Podrían guiarme para crear dicho control personalizado, de una forma correcta?

Muchas gracias.

MOD: Etiqueta GeSHi. Imagenes adaptadas a lo permitido.
#2
Hola compañeto, pues déjame decirte que lo logré, ahora ando un poquito ponchado es con el tema del Pan.

Mira el código que organicé para tal fin, del zoom respecto al puntero del mouse:
Imports System.Drawing


Public Class frm_camera

    ''' <summary>
    ''' Verifica si un botón del Mouse se ha presionado dentro de un control.
    ''' </summary>
    Dim mousePress 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>
    Dim mouseDown_Location As PointF
    Dim TraslationX_Graphics_old As Single = 0F
    Dim TraslationY_Graphics_old As Single = 0F
    ''' <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>
    Dim TraslationX_Graphics As Single = 0F
    ''' <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>
    Dim TraslationY_Graphics As Single = 0F
    ''' <summary>
    ''' Escala de zoom que debe aplicarse en ScaleTransform del Graphics, el cual se aciva con el evento MouseWheel.
    ''' </summary>
    Dim 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>
    Dim 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


    Private Sub transformar(canvas As Graphics)

        canvas.Clear(Color.Wheat)
        canvas.PixelOffsetMode = Drawing2D.PixelOffsetMode.Half
        canvas.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
        canvas.ScaleTransform(zoom, zoom)
        canvas.TranslateTransform(TraslationX_Graphics, TraslationY_Graphics)
        Dim pen As New Pen(Color.Red)
        pen.Width = 1 / zoom

        canvas.DrawRectangle(pen, 100, 100, 100, 50)

    End Sub

    ''' <summary>
    ''' Evento que se desencadena cuando se presiona un botón del Mouse en el Control.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown

        'Se verifica que ha presionado el botón izquierdo del Mouse.
        If e.Button = MouseButtons.Left Then
            '
            'Se verifica que no se tiene g
            'If Not mousePress = True Then

            'mousePress = True
            '
            'Obtiene las coordenadas del puntero del Mouse cuando se presionó el Mouse.
            mouseDown_Location = e.Location
            TraslationX_Graphics_old = TraslationX_Graphics
            TraslationY_Graphics_old = TraslationY_Graphics
            'End If

            PictureBox1.Invalidate()

        End If
    End Sub

    ''' <summary>
    ''' Evento que se produce cunado el puntero del mouse se mueve por el control.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove

        'Se verifica que ha presionado el botón izquierdo del Mouse.
        If e.Button = MouseButtons.Left Then
            '
            '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 haya los valores de desplazamiento.
            deltaX = mousePosNow.X - mouseDown_Location.X
            deltaY = mousePosNow.Y - mouseDown_Location.Y
            '
            '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.
            TraslationX_Graphics = (TraslationX_Graphics_old + (deltaX / zoom))
            TraslationX_Graphics = (TraslationY_Graphics_old + (deltaY / zoom))

            '
            'Obligo a redibujar el control.
            PictureBox1.Invalidate()

        End If

    End Sub

    Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp
        '
        '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.
        mousePress = False

    End Sub

    ''' <summary>
    ''' Evento que se produce cuando el Scroll del mouse se hace rodar.
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub PictureBox1_MouseWheel(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseWheel
        '
        'Actualizo el valor del zoom actual, antes de que se calcule el nuevo en este evento.
        zoom_old = zoom

        '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.
            zoom = Math.Min(zoom + zoom_increment, zoom_max)
        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
            zoom = Math.Max(zoom - zoom_increment, zoom_min)
        End If
        '
        'Se obtiene la posición actual del Mouse.
        Dim mousePosNow As Point = 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 - PictureBox1.Location.X
        deltaY = mousePosNow.Y - PictureBox1.Location.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 / zoom_old))
        oldGraphicsY = ((deltaY / 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 / zoom))
        newGraphicsY = ((deltaY / zoom))
        '
        'Los nuevos valores de Traslado del objeto Graphics se obtiene.
        TraslationX_Graphics = newGraphicsX - oldGraphicsX + TraslationX_Graphics
        TraslationY_Graphics = newGraphicsY - oldGraphicsY + TraslationY_Graphics
        'Se obliga a redibujar el control.
        PictureBox1.Invalidate()

    End Sub

    Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint

        'Envío el objeto Graphics, para que dibuje teniendo en cuenta las transformaciones.
        transformar(e.Graphics)

    End Sub


¿Es la forma correcta?. De ser así, te agradecería pudieras ayudarme con hacer el Pan o mover por medio del Mouse, teniendo presionado el Button.Left.

Muchas gracias.
#3
Muy buenos días compañero;

Es que una imagen tiene sus propiedades de location, cuestion que no tiene un Graphics, creame que yo le entiendo el procedimiento, de lo cual le estoy enteramente agradecido, pero eso no lo he podido trasladar a código con un Graphics.Todos los ejemplos que he visto por la internet todo lo hacen trabajando con BitMap, que es más sencillo, pero con un PictureBox, donde lo qu hago es obtener su e.Graphics, no he podido lograrlo. Por fa, ayudenme con un ejemplo de este tipo, se los ruego, hoy por mi mañana por ti.

Dios me lo bendiga.
#4
Hola compañero. De antemano muchas gracias por el código, pero la verdad nunca he trabajado con javascript, y por más que he tratado de buscar convertidores de código, no lo he encontrado, entiendo la idea más sin embargo con código no puedo lograrlo traspasar.

¿Es mucho pedirle, abusando de su amabilidad, pasarlo en sintaxis C# o VB.Net?. Preferiblemente VB.Net.

Mientras, trataré de seguir convertir ese código.

Dios me lo bendiga.
#5
Compañero, creame que llevo más de 2 semanas y no lo he logrado, le rogaría el favor que con un simple ejemplo de un rectángulo, pudiera ayudarme, que ya de ahí yo tomo la idea. Yo soy un igeniero civil, que me dedico a crear pequeños programas de utilidad, y estoy en un punto que ya no me sobran las ideas, pues lo que usted hace ver simple, ya para mí se ha vuelto un dolor de cabeza.

Añado un video ejemplar hecho en Autocad, con lo que deseo lograr:

https://www.dropbox.com/preview/autocad.mp4

Le pido por favor, con un simple ejemplo pequeño, me ilustre y yo de ahí en adelnate me voy.

Dios me lo bendiga.
#6
Hola, muy buenas tardes;

Tienes razón en eso, solo traté de ser lo más explícito posible. El inconveniente es que no es una imagen(es un objeto vectorial que en el proyecro dibujaré); sé que la solución está con el Graphics.TraslateTransform y ScaleTransform, combinándolas correctamente, lo cual he intentado de varias formas, pero no he logrado.

Seré lo más conciso:

1. La idea es que al hacer zoom con el MouseWheel del Picture, el gráfico dibujado se escale de tamaño teniendo como punto de origen la Posición Actual del Mouse. La idea es como este GIF.


La idea es emular lo mismo que hace Autocad, cuando se quiero hacer Zoom.



¿Es entendible lo que quiero decir?.

Agradezco pudieras ayudarme con una explicación más concisa, por ejemplo con un simple dibujo de un Rectángulo, y cuando se quiera hacer zoom con el Scroll del mouse(MouseWheel) el dibujo se acerque o se aleje, teniendo en cuenta el punto donde está el puntero del mouse.

Agradezco pueda ayudarme en esto compañero, pues compartir el conocimiento es lo mejor que podemos heredar.

Gracias por todo.
#7
Muy buenas tardes;

Mi idea es poder hacer zoom con uso de GDI+ en un dibujo que estoy haciendo de prueba, cuyo centro de enfoque sea la posición del mouse, el cual aplica el zoom por medio de un ScaleTransform en el evento MouseWheel del Picture. Lo que pasa actualmente es lo siguiente:

1. Ubicado en un punto del PictureBox con el cursor, hago uso del Scrool, con el fin de acercar o alejar el dibujo con respecto al punto de posición del mouse.


2. Luego de que se activa el evento MouseWheel, si se aleja o acerca el dibujo, pero lo que hace es alejarse del punto de foco(que corresponde a la posición del mouse).


La idea es, como clos programas CAD por ejemplo, es que se acerque o aleje el dibujo respecto a la posición del mouse, es decir, que la posición del mouse sea el centro de foco de la ampliación o reducción de lo dibujado. ¿Cómo puedo solucionar esto?.

El código que tengo actualmente es el siguiente:

Código (vbnet) [Seleccionar]
Option Strict On
Option Explicit On

Imports System.ComponentModel
Imports System.Text
Imports System.Drawing
Imports System.Drawing.Drawing2D


Partial Public Class Form1
    Shared Sub New()
        DevExpress.UserSkins.BonusSkins.Register()
        DevExpress.Skins.SkinManager.EnableFormSkins()
    End Sub
    Public Sub New()
        InitializeComponent()
        'Me.pe_dibujo.Properties.AllowZoomOnMouseWheel = DevExpress.Utils.DefaultBoolean.True
        ' Me.pe_dibujo.Properties.ZoomingOperationMode = DevExpress.XtraEditors.Repository.ZoomingOperationMode.MouseWheel

    End Sub

    Private Sub RadioGroup1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles rg_unidades.SelectedIndexChanged

        'Se verifica cual es el sistema de unidades seleccionado.
        Select Case rg_unidades.SelectedIndex

            'Caso pixeles.
            Case 0

                'Se describe el dibujo y relación de dibujo.
                lbl_comentario.Text = "Rectángulo de 50 x 50 pixeles" & Environment.NewLine &
                "en la posición (50,50)" & Environment.NewLine &
                "La regla mayor es de 50 pixeles."

            'Caso pulgadas.
            Case 1

                'Se describe el dibujo y relación de dibujo.
                lbl_comentario.Text = "Rectángulo de 1 x 1 pulgada" & Environment.NewLine &
                "en la posición (1,1)" &
                Environment.NewLine & "La regla mayor está cada pulgada."

            'Caso centímetros.
            Case 2

                'Se describe el dibujo y relación de dibujo.
                lbl_comentario.Text = "Rectángulo de 1 x 1 centímetro" & Environment.NewLine &
                "en la posición (1,1)" &
                Environment.NewLine & "La regla mayor está cada centìemtro."

        End Select

        'Se actualiza el dibujo.
        pe_dibujo.Invalidate()

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        'Al cargar el formulario se selecciona el sistema de unidades en Pixel por defecto.
        'Se envìa la selecciòn activando el control.
        rg_unidades.SelectedIndex = 1
        rg_unidades.Select()

    End Sub

    Private Sub pe_dibujo_Paint(sender As Object, e As PaintEventArgs) Handles pe_dibujo.Paint
        '
        'Variables para trabajar con el dibujo.
        Dim Rectangulo, Rectangulo2 As Rectangle
        Dim pincel_ancho_mm As Pen
        Dim pincel_acotar_mm As Pen
        Dim largo_linea_regla As Decimal
        Dim tickStep As Single
        Dim tickSize As Single
        Dim counter As Integer
        Dim marcas_principales_regla As Single
        Const ticks As String = "1424142414241"

        ' Se limpia el contenido dibujando previamente en el control.
        e.Graphics.Clear(Color.White)

        '---Se verifica que el sistema de unidades sea el Pixel.
        If (rg_unidades.SelectedIndex = 0) Then
            '
            'Se dibuja un rectángulo de 50 x 50 pixeles. Ubicado en las coordenadas de
            ' la pàgina a 50 pixeles a la derecha e inferior de la parte superior izquierda del control.
            Rectangulo = New Rectangle(50, 50, 50, 50)
            Rectangulo.Offset(50, 50)
            '
            'Se dibuja un rectángulo de 50 x 50 pixeles. Ubicado en las coordenadas de
            ' la pàgina a 50 pixeles a la derecha e inferior de la parte superior izquierda del control.
            Rectangulo2 = New Rectangle(100, 50, 50, 50)

            'El largo de la lìnea de la regla se harà siempre de 5 mm. Se convierte asì:
            '--- Largo = 5 mm*(a.Pix/Pulg)*(1 Pulg/25.4 mm)
            largo_linea_regla = CDec(CSng(5.0F * e.Graphics.DpiX / 25.4F))
            'Las marcas principales de la regla se haràn cada 50 pixeles de separamiento.
            marcas_principales_regla = 50.0F
            ' Se crea un pincel de dibujo de color determinado con un grosor en mm.
            pincel_ancho_mm = New Pen(Color.Black, CSng(0.1 * e.Graphics.DpiX / 25.4) / scale_zoom)
            '
            ' Se crea un pincel de dibujo de color determinado con un grosor en mm para las cotas.
            pincel_acotar_mm = New Pen(Color.Black, CSng(0.1 * e.Graphics.DpiX / 25.4) / scale_zoom)

            '
            '---Se verifica que el sistema de unidades sea la Pulgada.
        ElseIf (rg_unidades.SelectedIndex = 1) Then
            '
            ' Se escala a unidades de página en Pulgadas.
            e.Graphics.PageUnit = GraphicsUnit.Inch
            '
            ' Se crea un rectángulo de 1"x 1"( 1 pulgada cuadrada). Ubicado en las coordenadas de
            ' la pàgina a 1 pulgada a la derecha e inferior de la parte superior izquierda del control.
            Rectangulo = New Rectangle(1, 1, 1, 1)
            '
            ' Se crea un rectángulo de 1"x 1"( 1 pulgada cuadrada). Ubicado en las coordenadas de
            ' la pàgina a 1 pulgada a la derecha e inferior de la parte superior izquierda del control.
            Rectangulo2 = New Rectangle(2, 1, 1, 1)
            'El largo de la lìnea de la regla se harà siempre de 5 mm. Se convierte asì:
            '--- Largo = 5 m * (1 Pulg/25.4 mm)
            largo_linea_regla = CDec((5 / 25.4))
            'Las marcas principales de la regla se haràn cada 1 pulagada de separamiento.
            marcas_principales_regla = 1.0F
            '
            ' Se crea un pincel de dibujo de color determinado con un grosor en mm.
            pincel_ancho_mm = New Pen(Color.Black, CSng(0.1 / 25.4) / scale_zoom)
            '
            ' Se crea un pincel de dibujo de color determinado con un grosor en mm para las cotas.
            pincel_acotar_mm = New Pen(Color.Black, CSng(0.1 / 25.4) / scale_zoom)
            '
            '---Se verifica que el sistema de unidades sea el Centímetro.
        Else
            '
            ' Se usa escala unidades de la página a milímetros. Debe convertirse para centíemtros.
            e.Graphics.PageUnit = GraphicsUnit.Millimeter
            '
            'Se crea un rectángulo de 1cmx 1cm( 1 centímetro cuadrado). Ubicado en las coordenadas de
            ' la pàgina a 1 centímetro a la derecha e inferior de la parte superior izquierda del control.
            '
            '***Nota: 10 mm hacen 1 cm.
            '
            Rectangulo = New Rectangle(1 * 10, 1 * 10, 1 * 10, 1 * 10)
            '   '
            Rectangulo2 = New Rectangle(2 * 10, 1 * 10, 1 * 10, 1 * 10)
            '
            'El largo de la lìnea de la regla se harà siempre de 5 mm.
            largo_linea_regla = 5
            '
            'Las marcas principales de la regla se haràn cada 1 centímetro de separamiento.
            marcas_principales_regla = 1 * 10.0F
            '
            ' Se crea un pincel de dibujo de color determinado con un grosor en mm.
            pincel_ancho_mm = New Pen(Color.Black, 0.1F / scale_zoom)
            '
            ' Se crea un pincel de dibujo de color determinado con un grosor en mm para las cotas.
            pincel_acotar_mm = New Pen(Color.Black, 0.1F / scale_zoom)

        End If
        '
        '
        'Escalamos el dibujo de acuerdo al Zoom.
        e.Graphics.ScaleTransform(scale_zoom, scale_zoom, MatrixOrder.Append)
        e.Graphics.TranslateTransform(ultimaPosicion.X, ultimaPosicion.Y)

        '
        'Se pinta un área de la regla, la cual siempre es de 5 mm, independientemente
        'de la unidad de las coordenadas de la página.La regla se dibujarà siempre de 3" x 3"
        '--------------
        '
        'Se crea un cepillo o pintura Brush, teniendo en cuenta que su ancho siempre
        'serà de 5 mm por un largo de 3"(76.2 mm). Uno para la regla horizontal y otro para la
        'regla vetical. Existen 5 tipos: SolidBrush, HatchBrush, TextureBrush,LinearGradientBrush, PathGradientBrush(personalizado).
        '
        Dim fill_rec_horizontal As New SolidBrush(Color.LightYellow)
        Dim fill_rec_vertical As New SolidBrush(Color.BlanchedAlmond)
        'Punto de tipo Single, de la coordenada inicial de dibujo de el pintado del rectángulo.
        Dim coor_ini_fill As New PointF(0, 0)
        '
        'Para hacer el llenado del Brush debe tenerse en cuenta que para que se visualice de forma correcta, debe
        'tenerse en cuenta que al dibujar la regla en el For, se empezaràn a colocar cada (50 pix or 1" o 1 cm) des
        'fasado 5 mm(ancho de la regla), por lo que para dibujar bien el Brush con un largo de 3"(independiente de la unidad de medida)
        'debe tenerse en cuenta ese ancho adicional de llenado,
        'y su longitud debe calcularse asì L = largo_linea_regla + largo_linea_regla*(3"*25.4mm/largo_linea_regla(5 mm)) = largo_linea_regla*(1+15.24)
        'Recordar que 3" pulgadas es el largo de la regla a dibujar y que su valor en relaciones es:

        'Se rellena la regla en su parte vertical.
        e.Graphics.FillRectangle(fill_rec_vertical, coor_ini_fill.X, coor_ini_fill.Y, (largo_linea_regla / scale_zoom), largo_linea_regla * (1 + 15.24D))
        'Se rellena la regla en su parte horizontal.
        e.Graphics.FillRectangle(fill_rec_horizontal, coor_ini_fill.X, coor_ini_fill.Y, largo_linea_regla * (1 + 15.24D), largo_linea_regla / scale_zoom)
        'Se dibuja la lìnea de  borde la regla hasta donde se hace el relleno con color del Brush. Regla vertical.
        e.Graphics.DrawLine(pincel_ancho_mm, largo_linea_regla / scale_zoom, largo_linea_regla / scale_zoom, largo_linea_regla / scale_zoom, largo_linea_regla * (1 + 15.24D))
        'Se dibuja la lìnea de  borde la regla hasta donde se hace el relleno con color del Brush. Regla horizontal.
        e.Graphics.DrawLine(pincel_ancho_mm, largo_linea_regla / scale_zoom, largo_linea_regla / scale_zoom, largo_linea_regla * (1 + 15.24D), largo_linea_regla / scale_zoom)
        '
        '
        ' Dibuja las marcas principales y secundarias de la regla.
        For counter = 1 To ticks.Length

            If counter = 1 Then

                ' ----- Get the tick measurements. The "ticks" constant
                '       includes a set of "1", "2", and "4" values. "1"
                '       gives a full-size tick mark (for whole units),
                '       "2" gives a half-size tick mark, and "4" gives
                '       a 1/4-size tick mark.
                tickSize = CSng(Mid(ticks, counter, 1))
                tickStep = largo_linea_regla + ((marcas_principales_regla / 4) * (counter - 1))

                ' ----- Draw the horizontal ruler ticks.
                e.Graphics.DrawLine(pincel_ancho_mm, tickStep / scale_zoom, 0,
                   tickStep / scale_zoom, (largo_linea_regla / tickSize) / scale_zoom)

                ' ----- Draw the vertical ruler ticks.
                e.Graphics.DrawLine(pincel_ancho_mm, 0, tickStep / scale_zoom,
                  (largo_linea_regla / tickSize) / scale_zoom, tickStep / scale_zoom)

            Else
                ' ----- Get the tick measurements. The "ticks" constant
                '       includes a set of "1", "2", and "4" values. "1"
                '       gives a full-size tick mark (for whole units),
                '       "2" gives a half-size tick mark, and "4" gives
                '       a 1/4-size tick mark.
                tickSize = CSng(Mid(ticks, counter, 1))
                tickStep = largo_linea_regla + ((marcas_principales_regla / 4) * (counter - 1))

                ' ----- Draw the horizontal ruler ticks.
                e.Graphics.DrawLine(pincel_ancho_mm, tickStep, 0,
                   tickStep, (largo_linea_regla / tickSize) / scale_zoom)

                ' ----- Draw the vertical ruler ticks.
                e.Graphics.DrawLine(pincel_ancho_mm, 0, tickStep,
                  (largo_linea_regla / tickSize) / scale_zoom, tickStep)
            End If

        Next counter

        'Se transforma el eje del sistena de coordenadas de la pàgina a las del mmundo
        'desfasándolas 5.00 mm a la derecha e inferior del vèrtice superior izquierdo
        'que son el eje del sistema de coordendas del dispositivo y pàgina. Esto inde-
        'pendiente de las unidades de la pàgina.
        e.Graphics.TranslateTransform(largo_linea_regla, largo_linea_regla)
        '
        'Dibuja un rectángulo de un ancho determinado del pixel(siempre en mm), con
        'un tamaño determinado.
        e.Graphics.DrawRectangle(pincel_ancho_mm, Rectangulo)
        '
        'Dibujo un rectangulo pegado al anterior.
        e.Graphics.DrawRectangle(pincel_ancho_mm, Rectangulo2)
        '
        'Código para dibujar una regla en el PictureBox.
        Dim gp As New Drawing.Drawing2D.GraphicsPath
        gp.AddLine(0, 0, 2, -5)
        gp.AddLine(0, 0, -2, -5)
        gp.AddLine(-2, -5, 2, -5)
        pincel_acotar_mm.CustomEndCap = New Drawing2D.CustomLineCap(gp, Nothing)
        pincel_acotar_mm.CustomStartCap = New Drawing2D.CustomLineCap(gp, Nothing)
        e.Graphics.DrawLine(pincel_acotar_mm, New PointF(CSng(Rectangulo.X * 0.95), Rectangulo.Y), New PointF(CSng(Rectangulo.X * 0.95), Rectangulo.Y + Rectangulo.Height))
        Dim myFont As New Font("Courier", 2, FontStyle.Regular, GraphicsUnit.Millimeter, 0)
        e.Graphics.DrawString(Rectangulo.Height.ToString, myFont, Brushes.Black, CSng(Rectangulo.X * 0.5), CSng(Rectangulo.Y + Rectangulo.Height / 2))
        '
        'Se librea el picenl de dibujo.
        pincel_ancho_mm.Dispose()

    End Sub

    'Factor de aumento o disminución del zoom(10%).
    Dim factor_Delta_zoom As Single = 0.1
    'Escala de un 100%, cuya variable será la que variará de acuerdo al MouseWheel.
    Dim scale_zoom As Single = 1

    Private Sub pe_dibujo_Properties_MouseWheel(sender As Object, e As MouseEventArgs) Handles pe_dibujo.Properties.MouseWheel

        'Verifico que el delta del cambio del Scrool haya sido positivo.
        If e.Delta > 0 Then
            '
            'En este caso aumento la escala del zoom
            scale_zoom += factor_Delta_zoom
        Else
            '
            'En este caso disminuyo la escala del zoom.
            scale_zoom -= factor_Delta_zoom
            '
        End If
        '
        'Invoco el redibujado del control del PictureBox.
        pe_dibujo.Invalidate()
'
    End Sub

End Class
   


Agradeciera mucho me pudieran guiar en este caso, porque la verdad ya no se como lograrlo.

Muchas gracias.

MOD: Imagenes adaptadas a lo permitido. Etiquetas GeSHi.