[APORTE] Screen-Region Selector (para capturadores de pantalla)

Iniciado por Eleкtro, 28 Junio 2014, 08:06 AM

0 Miembros y 1 Visitante están viendo este tema.

Eleкtro

Hola

Desarrollé este Snippet para que dibuja una forma cuadrada/rectangular sobre la pantalla para seleccionar un área de la imagen en movimiento, y devuelve los datos de la estructura del rectángulo seleccionado para, posteriormente, poder capturar esa región de la imagen.

Hay 2 formas (que yo sepa al menos) de llevar esto a cabo, una es "congelando" la imagen, y la otra es en tiempo real, yo opté por la segunda opción, a pesar de ser mucho más complicada es lo que se adaptaba a mis necesidades.

Espero que puedan sacar algo de provecho en este código.

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author           : Elektro
' Last Modified On : 06-03-2014
' ***********************************************************************
' <copyright file="RegionSelector.vb" company="Elektro Studios">
'     Copyright (c) Elektro Studios. All rights reserved.
' </copyright>
' ***********************************************************************

#Region " Usage Examples "

'Public Class Form1

'    Dim SelectedRegion As Rectangle = Rectangle.Empty
'    Dim RegionSelectorIsWorking As Boolean = False

'    Private Sub Button_Click() Handles Button1.Click
'        GetScreenRegion()
'    End Sub

'    Public Sub GetScreenRegion()

'        Dim Callback As RegionSelector.RegionSelectedDelegate

'        Dim Selector As New RegionSelector(BorderColor:=Color.YellowGreen,
'                                           BorderSize:=3,
'                                           backgroundcolor:=Color.YellowGreen,
'                                           BackgroundOpacity:=0.06R)

'        Select Case RegionSelectorIsWorking

'            Case True ' Only one selection at once!
'                Exit Sub

'            Case Else
'                RegionSelectorIsWorking = True
'                Callback = New RegionSelector.RegionSelectedDelegate(AddressOf SelectionFinished)

'                With Selector
'                    .Callback = Callback
'                    .Show()
'                End With

'        End Select

'        ' Don't do any stuff here... do it in Rectangle Drawn...

'    End Sub

'    Private Sub SelectionFinished(ByVal Region As Rectangle)

'        RegionSelectorIsWorking = False ' Allow draw again.
'        Me.SelectedRegion = Region

'        Dim sb As New System.Text.StringBuilder
'        With sb
'            .AppendLine("Selected Area")
'            .AppendLine()
'            .AppendLine("· Size")
'            .AppendLine(String.Format("Width: {0}", CStr(SelectedRegion.Width)))
'            .AppendLine(String.Format("Height: {0}", CStr(SelectedRegion.Height)))
'            .AppendLine()
'            .AppendLine("· Coordinates")
'            .AppendLine(String.Format("Top: {0}", CStr(SelectedRegion.Top)))
'            .AppendLine(String.Format("Left: {0}", CStr(SelectedRegion.Left)))
'            .AppendLine(String.Format("Right: {0}", CStr(SelectedRegion.Right)))
'            .AppendLine(String.Format("Bottom: {0}", CStr(SelectedRegion.Bottom)))
'            .AppendLine()
'        End With

'        MessageBox.Show(sb.ToString)

'    End Sub

'End Class

#End Region

''' <summary>
''' Selects a region on the Screen.
''' </summary>
Public NotInheritable Class RegionSelector : Inherits Form

#Region " Delegates "

   ''' <summary>
   ''' Delegate RegionSelectedDelegate.
   ''' </summary>
   ''' <param name="Region">The region.</param>
   Public Delegate Sub RegionSelectedDelegate(ByVal Region As Rectangle)

#End Region

#Region " Properties "

   ''' <summary>
   ''' Callback to be invoked when drawing is done...
   ''' </summary>
   ''' <value>Delegate of Region Selected</value>
   Public Property Callback As RegionSelectedDelegate = Nothing

   ''' <summary>
   ''' Gets or sets the border size of the region selector.
   ''' </summary>
   ''' <value>The size of the border.</value>
   Public Property BorderSize As Integer = 2

   ''' <summary>
   ''' Gets or sets the border color of the region selector.
   ''' </summary>
   ''' <value>The color of the border.</value>
   Public Property BorderColor As Color = Color.Red

   ''' <summary>
   ''' Gets or sets the background color of the region selector.
   ''' </summary>
   ''' <value>The color of the border.</value>
   Public Property BackgroundColor As Color = Color.RoyalBlue

   ''' <summary>
   ''' Gets or sets the background opacity of the region selector.
   ''' </summary>
   ''' <value>The color of the border.</value>
   Public Property BackgroundOpacity As Double = 0.08R

   ''' <summary>
   ''' Gets the rectangle that contains the selected region.
   ''' </summary>
   Public ReadOnly Property SelectedRegion As Rectangle
       Get
           Return Me.DrawRect
       End Get
   End Property

#End Region

#Region " Objects "

   ''' <summary>
   ''' Indicates the initial location when the mouse left button is clicked.
   ''' </summary>
   Private InitialLocation As Point = Point.Empty

   ''' <summary>
   ''' The rectangle where to draw the region.
   ''' </summary>
   Public DrawRect As Rectangle = Rectangle.Empty

   ''' <summary>
   ''' The Graphics object to draw on the screen.
   ''' </summary>
   Private ScreenGraphic As Graphics = Graphics.FromHwnd(IntPtr.Zero)

   ''' <summary>
   ''' Indicates the Rectangle Size.
   ''' </summary>
   Dim DrawSize As Size

   ''' <summary>
   ''' Indicates the draw form.
   ''' </summary>
   Dim DrawForm As Form

   ''' <summary>
   ''' Indicates whether the RegionSelector is busy drawing the rectangle.
   ''' </summary>
   Public IsDrawing As Boolean = False

#End Region

#Region " Constructors "

   ''' <summary>
   ''' Initializes a new instance of the <see cref="RegionSelector"/> class.
   ''' </summary>
   Public Sub New()
   End Sub

   ''' <summary>
   ''' Initializes a new instance of the <see cref="RegionSelector" /> class.
   ''' </summary>
   ''' <param name="BorderColor">Indicates the border color of the region selector.</param>
   ''' <param name="BorderSize">Indicates the border size of the region selector.</param>
   ''' <param name="BackgroundColor">Indicates the background color of the region selector.</param>
   ''' <param name="BackgroundOpacity">Indicates the background opacity size of the region selector.</param>
   Public Sub New(Optional ByVal BorderColor As Color = Nothing,
                  Optional ByVal BorderSize As Integer = 2,
                  Optional ByVal BackgroundColor As Color = Nothing,
                  Optional ByVal BackgroundOpacity As Double = 0.1R)

       If BorderColor = Nothing _
       OrElse BorderColor = Color.Transparent Then
           BorderColor = Color.Red
       End If

       If BackgroundColor = Nothing _
       OrElse BackgroundColor = Color.Transparent Then
           BackgroundColor = Color.Black
       End If

       Me.BorderSize = BorderSize
       Me.BorderColor = BorderColor
       Me.BackgroundOpacity = BackgroundOpacity
       Me.BackgroundColor = BackgroundColor

   End Sub

#End Region

#Region " Event Handlers "

   ''' <summary>
   ''' Handles the Load event of the RegionSelector.
   ''' </summary>
   ''' <param name="sender">The source of the event.</param>
   ''' <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
   Private Sub RegionSelector_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

       Me.SuspendLayout()

       Me.AutoScaleMode = AutoScaleMode.None
       Me.BackColor = Me.BackgroundColor
       Me.BackgroundImageLayout = ImageLayout.None
       Me.CausesValidation = False
       Me.ClientSize = New Size(0, 0)
       Me.ControlBox = False
       Me.Cursor = Cursors.Cross
       Me.DoubleBuffered = True
       Me.FormBorderStyle = FormBorderStyle.None
       Me.MaximizeBox = False
       Me.MinimizeBox = False
       Me.Name = "RegionSelector"
       Me.Opacity = Me.BackgroundOpacity
       Me.ShowIcon = False
       Me.ShowInTaskbar = False
       Me.SizeGripStyle = SizeGripStyle.Hide
       Me.StartPosition = FormStartPosition.CenterScreen
       Me.TopMost = False
       Me.WindowState = FormWindowState.Maximized

       Me.ResumeLayout(False)

       Me.DrawForm = New DrawingRegionClass(Me)
       With DrawForm
           .AutoScaleMode = AutoScaleMode.None
           .BackColor = Color.Tomato
           .BackgroundImageLayout = ImageLayout.None
           .ControlBox = False
           .FormBorderStyle = FormBorderStyle.None
           .MaximizeBox = False
           .MinimizeBox = False
           .ShowIcon = False
           .ShowInTaskbar = False
           .SizeGripStyle = SizeGripStyle.Hide
           .StartPosition = FormStartPosition.CenterScreen
           .TopLevel = True
           .TopMost = True
           .TransparencyKey = Color.Tomato
           .WindowState = FormWindowState.Maximized
       End With

       Me.AddOwnedForm(Me.DrawForm)
       Me.DrawForm.Show()

   End Sub

   ''' <summary>
   ''' Raises the <see cref="E:System.Windows.Forms.Control.MouseDown" /> event.
   ''' </summary>
   ''' <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.</param>
   Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)

       If e.Button = MouseButtons.Left Then
           Me.InitialLocation = e.Location
           Me.IsDrawing = True
       End If

   End Sub

   ''' <summary>
   ''' Raises the <see cref="E:System.Windows.Forms.Control.MouseUp" /> event.
   ''' </summary>
   ''' <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.</param>
   Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)

       Me.IsDrawing = False
       Callback.Invoke(SelectedRegion)
       Me.Close() ' Must be called last.

   End Sub

   ''' <summary>
   ''' Raises the <see cref="E:System.Windows.Forms.Control.MouseMove" /> event.
   ''' </summary>
   ''' <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.</param>
   Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)

       If Me.IsDrawing Then

           Me.DrawSize = New Size(e.X - Me.InitialLocation.X, e.Y - Me.InitialLocation.Y)
           Me.DrawRect = New Rectangle(Me.InitialLocation, Me.DrawSize)

           If Me.DrawRect.Height < 0 Then
               Me.DrawRect.Height = Math.Abs(Me.DrawRect.Height)
               Me.DrawRect.Y -= Me.DrawRect.Height
           End If

           If Me.DrawRect.Width < 0 Then
               Me.DrawRect.Width = Math.Abs(Me.DrawRect.Width)
               Me.DrawRect.X -= Me.DrawRect.Width
           End If

           Me.DrawForm.Invalidate()

       End If

   End Sub

#End Region

End Class

''' <summary>
''' Class DrawingRegionClass. This class cannot be inherited.
''' </summary>
Friend NotInheritable Class DrawingRegionClass : Inherits Form

   Private DrawParent As RegionSelector

   Public Sub New(ByVal Parent As Form)

       Me.DrawParent = Parent

   End Sub

   Protected Overrides Sub OnPaintBackground(ByVal e As PaintEventArgs)

       Dim Bg As Bitmap
       Dim Canvas As Graphics

       If Me.DrawParent.IsDrawing Then

           Bg = New Bitmap(Width, Height)
           Canvas = Graphics.FromImage(Bg)
           Canvas.Clear(Color.Tomato)

           Using pen As New Pen(Me.DrawParent.BorderColor, Me.DrawParent.BorderSize)
               Canvas.DrawRectangle(pen, Me.DrawParent.DrawRect)
           End Using

           Canvas.Dispose()
           e.Graphics.DrawImage(Bg, 0, 0, Width, Height)
           Bg.Dispose()

       Else
           MyBase.OnPaintBackground(e)
       End If

   End Sub

End Class



Complemento adicional:

Código (vbnet) [Seleccionar]
    ' Take Region ScreenShot
    ' ( By Elektro )
    '
    ' Usage Examples :
    '
    ' Dim RegionScreenShot As Bitmap = TakeRegionScreenShot(New Point(0, 0), New Size(256, 256))
    ' Dim RegionScreenShot As Bitmap = TakeRegionScreenShot(New Rectangle With {.Location = Point.Empty, .Size = New Size(256, 256)})
    ' PictureBox1.BackgroundImage = RegionScreenShot
    ' RegionScreenShot.Save("C:\RegionScreenShot.png", Imaging.ImageFormat.Png)
    '
    ''' <summary>
    ''' Takes an image screenshot of an specific screen region.
    ''' </summary>
    ''' <param name="Coordinates">
    ''' The X-coordinate is the point at the upper-left corner of the region.
    ''' The Y-coordinate is the point at the upper-left corner of the region.
    ''' </param>
    ''' <param name="Size">Indicates the size of the area to be transferred.</param>
    ''' <param name="PixelFormat">Indicates the Bitmap pixel format.</param>
    ''' <returns>Bitmap.</returns>
    Private Function TakeRegionScreenShot(ByVal Coordinates As Point,
                                          ByVal [Size] As Size,
                                          Optional ByVal [PixelFormat] As Imaging.PixelFormat =
                                                                          Imaging.PixelFormat.Format24bppRgb) As Bitmap

        Using ScreenImage As New Bitmap([Size].Width, [Size].Height, [PixelFormat])

            Using ScreenGraphics As Graphics = Graphics.FromImage(ScreenImage)

                ScreenGraphics.CopyFromScreen(Coordinates, Point.Empty, ScreenImage.Size)

            End Using ' ScreenGraphics

            Return CType(ScreenImage.Clone, Bitmap)

        End Using ' ScreenImage

    End Function

    ''' <summary>
    ''' Takes an image screenshot of an specific screen region.
    ''' </summary>
    ''' <param name="Region">Indicates a Rectangle structure that contains the region coordinates and the size.</param>
    ''' <param name="PixelFormat">Indicates the Bitmap pixel format.</param>
    ''' <returns>Bitmap.</returns>
    Private Function TakeRegionScreenShot(ByVal [Region] As Rectangle,
                                          Optional ByVal [PixelFormat] As Imaging.PixelFormat =
                                                                          Imaging.PixelFormat.Format24bppRgb) As Bitmap

        Return TakeRegionScreenShot([Region].Location, [Region].Size, [PixelFormat])

    End Function