Ferramentas de Usuário

Ferramentas de Site


dev_net:vb.net:lupa

GDI+ - Lupa

Introdução

A framework oferece-nos um acesso amigável à API GDI+ nativa do sistema operativo, que é o túnel para o desenho de gráficos bidimensionais no ecran ou na impressora. Através deste acesso, são nos disponibilizados métodos para desenhar virtualmente tudo o que a nossa imaginação possa conceber. Podemos também utilizar estes recursos para manipular imagens em qualquer nível. Para o demonstrar, vamos passo a passo construír uma lupa do ambiente de trabalho.

Este “túnel para a GDI+” encontra-se disponível na Framework através do namespace System.Drawing

A lógica

Essencialmente, o que se faz é capturar uma imagem do ecran sempre que for detectado um movimento do rato e de seguida multiplicar o "zoom" por cada dimensão da imagem capturada e redesenha-se a imagem com as novas dimensões, o que vai provocar um efeito de aumento.

A prática

A falta de explicação no corpo do artigo é compensada por os comentários nos blocos de código

Comecemos por declarar e instanciar tudo o que precisamos para a nossa lupa

    'Quatro valores, a representar dois pontos, para determinar se existiu movimento no rato
    Private X1 As Integer = 0
    Private X2 As Integer = 0
    Private Y1 As Integer = 0
    Private Y2 As Integer = 0
    'O valor de Zoom, utilizado para multiplicar dimensões
    Private Zoom As Integer = 3
    'A área visível da lupa
    Private AreaLupa As New Rectangle(0, 0, 200, 200)
    'A área de captura. 200 pixeis significa que vai capturar 200/2 pixeis de cada lado do centro do ponteiro
    Private AreaCaptura As Integer = 200
    'instância do rectangulo para determinar os valores multiplicado por o zoom
    Private AreaAumentada As New Rectangle(0, 0, AreaLupa.Width * Zoom, AreaLupa.Height * Zoom)
    'O temporizador que detecta o movimento
    Private WithEvents TMR As New Timer With {.enabled = True, .interval = 1}

De seguida, as configurações necessárias ao form

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Configuramos o aspecto,localização e dimensão do nosso form
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
        Me.Width = AreaLupa.Width
        Me.Height = AreaLupa.Height
        Me.Top = 5
        Me.Left = 5
        'estipulamos também que este form se vai encontrar sempre no topo
        Me.TopMost = True
    End Sub

Um pequeno pormenor de escape

    Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
        'Como temos o TopMost=True, preparamos este escape para evitar problemas
        End
    End Sub

E por fim, o código do temporizador para determinar se o rato foi mexido e consequentemente capturar uma nova imagem e aplicar zoom

    Private Sub DetectarEDesenhar(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TMR.Tick
 
        'Vamos buscar a posição actual do rato
        X1 = MousePosition.X
        Y1 = MousePosition.Y
 
        'E vamos verificar se o que acabamos de apanhar coincide com o que tinhamos apanhado antes
        'Se for diferente, significa que o rato se moveu
        If X1 <> X2 Or Y1 <> Y2 Then
            'Como o rato se moveu, temos de actualizar a imagem da lupa
 
            'Começamos por determinar o ponto esquerdo superior da captura, a partir das coordenadas do ponteiro
            'Precisamos do ponto esquerdo superior porque o método de captura trabalha com "Size"
            Dim Origem As New Point(X1 - CInt(AreaCaptura / 2), Y1 - CInt(AreaCaptura / 2))
 
            'Instanciamos um novo Bitmap com a área de captura exactamente
            'Este bitmap representa a captura feita ao ecran
            Dim Captura As New Bitmap(AreaCaptura, AreaCaptura)
            'Declaramos uma variável do tipo Graphics que associamos ao Bitmap Captura préviamente criado
            Dim IG As Graphics = Graphics.FromImage(Captura)
 
            'Como temos um objecto Graphics com referência à dimensão da nossa captura, está na altura de
            'efectuar a captura propriamente dita e para isso utilizamos o método CopyFromScreen
            IG.CopyFromScreen(Origem, New Point(0, 0), New Size(AreaLupa.Width, AreaLupa.Height))
 
            'Declaramos uma outra variável do tipo Graphics para se referenciar desta vez à form
            Dim FG As Graphics = Me.CreateGraphics
            'Determinamos a interpolação para alta qualidade, para que a imagem se deforme o mínimo possível no aumento
            FG.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
            'E desenhamos a imagem capturada para a dimensão calculada com o Zoom, fazendo-a aumentar
            FG.DrawImage(Captura, CInt(0 - ((AreaAumentada.Width - AreaLupa.Width) / 2)), CInt(0 - ((AreaAumentada.Height - AreaLupa.Height) / 2)), AreaAumentada.Width, AreaAumentada.Height)
 
            'Por fim, igualamos as variáveis para dizer que a última posição do rato é a actual
            X2 = X1
            Y2 = Y1
        End If
 
    End Sub

O exemplo completo Crie um novo projecto, e substitua todo o código do form de arranque por este:

Public Class Form1
 
    'Quatro valores, a representar dois pontos, para determinar se existiu movimento no rato
    Private X1 As Integer = 0
    Private X2 As Integer = 0
    Private Y1 As Integer = 1
    Private Y2 As Integer = 1
    'O valor de Zoom, utilizado para multiplicar dimensões
    Private Zoom As Integer = 3
    'A área visível da lupa
    Private AreaLupa As New Rectangle(0, 0, 200, 200)
    'A área de captura. 200 pixeis significa que vai capturar 200/2 pixeis de cada lado do centro do ponteiro
    Private AreaCaptura As Integer = 200
    'instância do rectangulo para determinar os valores multiplicado por o zoom
    Private AreaAumentada As New Rectangle(0, 0, AreaLupa.Width * Zoom, AreaLupa.Height * Zoom)
    'O temporizador que detecta o movimento
    Private WithEvents TMR As New Timer With {.enabled = True, .interval = 1}
 
    Private Sub DetectarEDesenhar(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TMR.Tick
 
        'Vamos buscar a posição actual do rato
        X1 = MousePosition.X
        Y1 = MousePosition.Y
 
        'E vamos verificar se o que acabamos de apanhar coincide com o que tinhamos apanhado antes
        'Se for diferente, significa que o rato se moveu
        If X1 <> X2 Or Y1 <> Y2 Then
            'Como o rato se moveu, temos de actualizar a imagem da lupa
 
            'Começamos por determinar o ponto esquerdo superior da captura, a partir das coordenadas do ponteiro
            'Precisamos do ponto esquerdo superior porque o método de captura trabalha com "Size"
            Dim Origem As New Point(X1 - CInt(AreaCaptura / 2), Y1 - CInt(AreaCaptura / 2))
 
            'Instanciamos um novo Bitmap com a área de captura exactamente
            'Este bitmap representa a captura feita ao ecran
            Dim Captura As New Bitmap(AreaCaptura, AreaCaptura)
            'Declaramos uma variável do tipo Graphics que associamos ao Bitmap Captura préviamente criado
            Dim IG As Graphics = Graphics.FromImage(Captura)
 
            'Como temos um objecto Graphics com referência à dimensão da nossa captura, está na altura de
            'efectuar a captura propriamente dita e para isso utilizamos o método CopyFromScreen
            IG.CopyFromScreen(Origem, New Point(0, 0), New Size(AreaLupa.Width, AreaLupa.Height))
 
            'Declaramos uma outra variável do tipo Graphics para se referenciar desta vez à form
            Dim FG As Graphics = Me.CreateGraphics
            'Determinamos a interpolação para alta qualidade, para que a imagem se deforme o mínimo possível no aumento
            FG.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
            'E desenhamos a imagem capturada para a dimensão calculada com o Zoom, fazendo-a aumentar
            FG.DrawImage(Captura, CInt(0 - ((AreaAumentada.Width - AreaLupa.Width) / 2)), CInt(0 - ((AreaAumentada.Height - AreaLupa.Height) / 2)), AreaAumentada.Width, AreaAumentada.Height)
 
            'Por fim, igualamos as variáveis para dizer que a última posição do rato é a actual
            X2 = X1
            Y2 = Y1
        End If
 
    End Sub
 
    Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
        'Como temos o TopMost=True, preparamos este escape para evitar problemas
        End
    End Sub
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Configuramos o aspecto,localização e dimensão do nosso form
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
        Me.Width = AreaLupa.Width
        Me.Height = AreaLupa.Height
        Me.Top = 5
        Me.Left = 5
        'estipulamos também que este form se vai encontrar sempre no topo
        Me.TopMost = True
    End Sub
End Class
dev_net/vb.net/lupa.txt · Última modificação em: 2018/05/14 21:37 (edição externa)