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
' *********************************************************************** ' 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
' 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