Solved

Selection Tool for a Screen Capture Software in VB.NET

Posted on 2004-07-30
5
1,396 Views
Last Modified: 2008-02-20
Hi,

I am working on a screen capture software and am trying to sort out how to make a selection tool to select a specific area of the screen or a specific window. Any help or guidance in this will be greatly appreciated. So far i can take a snap of an area using a simple form. This application is being made in Visual Basic .NET.

Thanks for all your support in this matter.
0
Comment
Question by:bkniazi
  • 2
  • 2
5 Comments
 
LVL 27

Expert Comment

by:planocz
ID: 11676659
Hi,

Look at this link...
I think you maybe  able to add some mouse moves to work with this code to make a screen capture software

http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/VB_DOT_NET/Q_21074886.html
0
 
LVL 85

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 150 total points
ID: 11677727
Here is a sample application that demonstrates how to accomplish Rubberbanding in a picturebox.

Hope you find it useful,

Idle_Mind

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(Form1))
        Me.PictureBox1 = New System.Windows.Forms.PictureBox
        Me.SuspendLayout()
        '
        'PictureBox1
        '
        Me.PictureBox1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.PictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.PictureBox1.Image = CType(resources.GetObject("PictureBox1.Image"), System.Drawing.Image)
        Me.PictureBox1.Location = New System.Drawing.Point(8, 8)
        Me.PictureBox1.Name = "PictureBox1"
        Me.PictureBox1.Size = New System.Drawing.Size(336, 256)
        Me.PictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage
        Me.PictureBox1.TabIndex = 0
        Me.PictureBox1.TabStop = False
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(352, 278)
        Me.Controls.Add(Me.PictureBox1)
        Me.Name = "Form1"
        Me.Text = "RubberBanding in a PictureBox"
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private startX As Integer
    Private startY As Integer
    Private lastX As Integer
    Private lastY As Integer
    Private rubberbanding As Boolean = False
    Private firstBoxDrawn As Boolean = False

    Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
        If e.Button = MouseButtons.Left Then
            rubberbanding = True
            firstBoxDrawn = False
            Dim p As Point = PictureBox1.PointToScreen(New Point(e.X, e.Y))
            startX = p.X
            startY = p.Y
            Cursor.Clip = PictureBox1.RectangleToScreen(New Rectangle(0, 0, PictureBox1.Width, PictureBox1.Height))
        End If
    End Sub

    Private Sub Form1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
        If rubberbanding And e.KeyChar = Microsoft.VisualBasic.ChrW(27) Then
            rubberbanding = False
            Cursor.Clip = New Rectangle(0, 0, Screen.GetBounds(New Point(0, 0)).Width, Screen.GetBounds(New Point(0, 0)).Height)
            If firstBoxDrawn Then
                ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, lastX - startX, lastY - startY), Color.Black, FrameStyle.Dashed)
            End If
        End If
    End Sub

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        If rubberbanding Then
            Dim p As Point = PictureBox1.PointToScreen(New Point(e.X, e.Y))
            If Not firstBoxDrawn Then
                firstBoxDrawn = True
                ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, p.X - startX, p.Y - startY), Color.Black, FrameStyle.Dashed)
            Else
                ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, lastX - startX, lastY - startY), Color.Black, FrameStyle.Dashed)
                ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, p.X - startX, p.Y - startY), Color.Black, FrameStyle.Dashed)
            End If
            lastX = p.X
            lastY = p.Y
        End If
    End Sub

    Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
        If rubberbanding And e.Button = MouseButtons.Left Then
            Cursor.Clip = New Rectangle(0, 0, Screen.GetBounds(New Point(0, 0)).Width, Screen.GetBounds(New Point(0, 0)).Height)
            rubberbanding = False
            If firstBoxDrawn Then
                Dim r As Rectangle = New Rectangle(startX, startY, lastX - startX, lastY - startY)
                ControlPaint.DrawReversibleFrame(r, Color.Black, FrameStyle.Dashed)
                r = PictureBox1.RectangleToClient(r)
                RectangleSelected(r)
            End If
        End If
    End Sub

    Private Sub RectangleSelected(ByVal selectionArea As Rectangle)
        ' do something with your selected area...
        ' the selectionarea is in client coordinates, relative to the picturebox, not the screen
        MsgBox(selectionArea.ToString)
    End Sub

End Class
0
 
LVL 27

Expert Comment

by:planocz
ID: 11677810
Thanks Idle_Mind
  I had not seen this before.
0
 
LVL 28

Assisted Solution

by:iboutchkine
iboutchkine earned 100 total points
ID: 11679397
Check this. It might be helpful

This program uses a PictureBox's MouseDown, MouseMove, and MouseUp event
handlers to let the user scribble to select an area. It saves the points
drawn by the user in the m_Points array.


The MouseUp event handler adds a point to close the area if necessary.
It then uses the points to create a graphics Path object. It makes a
Bitmap containing a copy of a background picture and then makes a
Graphics object attached to the Bitmap. It uses the Graphics object's
SetClip method to restrict drawing to the Path and then uses DrawImage
to copy the original picture onto the background (in the restricted
area).


Private m_Points() As Point
Private m_MaxPoint As Integer


' Start selecting a region.
Private Sub picVisible_MouseDown(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles picVisible.MouseDown
    ' Erase any previous drawing.
    picVisible.Image = DirectCast(picOriginal.Image.Clone, Bitmap)


    ' Save the starting point.
    m_MaxPoint = 0
    ReDim m_Points(m_MaxPoint)
    m_Points(m_MaxPoint).X = e.X
    m_Points(m_MaxPoint).Y = e.Y
End Sub


' Continue selecting a region.
Private Sub picVisible_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles picVisible.MouseMove
    ' Do nothing if we're not selecting a region.
    If m_Points Is Nothing Then Exit Sub


    ' Save the new point.
    m_MaxPoint += 1
    ReDim Preserve m_Points(m_MaxPoint)
    m_Points(m_MaxPoint).X = e.X
    m_Points(m_MaxPoint).Y = e.Y


    ' Draw the latest line.
    Dim gr As Graphics = picVisible.CreateGraphics
    gr.DrawLine(Pens.Yellow, _
        m_Points(m_MaxPoint).X, _
        m_Points(m_MaxPoint).Y, _
        m_Points(m_MaxPoint - 1).X, _
        m_Points(m_MaxPoint - 1).Y)
End Sub


' Finish selecting a region.
Private Sub picVisible_MouseUp(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles picVisible.MouseUp
    ' Do nothing if we're not selecting a region.
    If m_Points Is Nothing Then Exit Sub


    ' Close the region.
    If (m_Points(0).X <> m_Points(m_MaxPoint).X) Or _
       (m_Points(0).Y <> m_Points(m_MaxPoint).Y) _
    Then
        ' Save the new point.
        m_MaxPoint += 1
        ReDim Preserve m_Points(m_MaxPoint)
        m_Points(m_MaxPoint).X = m_Points(0).X
        m_Points(m_MaxPoint).Y = m_Points(0).Y
    End If


    ' Make the points into a Path.
    Dim selected_path As New
System.Drawing.Drawing2D.GraphicsPath(Drawing2D.FillMode.Winding)
    selected_path.AddLines(m_Points)


    ' Make the drawing permanent.
    Dim bm_visible As Bitmap = DirectCast(picOriginal.Image.Clone,
Bitmap)
    Dim gr_visible As Graphics = Graphics.FromImage(bm_visible)
    gr_visible.DrawPath(Pens.Orange, selected_path)
    picVisible.Image = bm_visible


    ' Copy the picture onto picResult,
    ' restricting it to the selected region.
    Dim bm_result As Bitmap = DirectCast(picBackground.Image.Clone,
Bitmap)
    Dim gr_result As Graphics = Graphics.FromImage(bm_result)
    ' Clip to the path.
    gr_result.SetClip(selected_path)
    ' Copy the image.
    gr_result.DrawImage(picOriginal.Image, 0, 0)
    ' Display the result.
    picResult.Image = bm_result


    ' We're no longer selecting a region.
    m_Points = Nothing
End Sub

0
 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 150 total points
ID: 11681198
Here is a complete screen capture demo I have written.  It draws a rubberband box directly on the desktop and uses very fast API calls to copy the selected area to a picturebox on the form.  To select an area position your mouse where you want to start the selection and press F9.  Now move your mouse to select an area and push F9 again.  There are no mouse clicks involved in the process.  I registered F9 as a system-wide hotkey so the app doesn't need to be in focus for this to work.  If you set the Icon property of the NotifyIcon1 control to a valid icon then the application will minimize to the tray instead of the taskbar.

Regards,

Idle_Mind


Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents Panel1 As System.Windows.Forms.Panel
    Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
    Friend WithEvents Label1 As System.Windows.Forms.Label
    Friend WithEvents Timer1 As System.Windows.Forms.Timer
    Friend WithEvents NotifyIcon1 As System.Windows.Forms.NotifyIcon
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Me.Panel1 = New System.Windows.Forms.Panel
        Me.PictureBox1 = New System.Windows.Forms.PictureBox
        Me.Label1 = New System.Windows.Forms.Label
        Me.Timer1 = New System.Windows.Forms.Timer(Me.components)
        Me.NotifyIcon1 = New System.Windows.Forms.NotifyIcon(Me.components)
        Me.Panel1.SuspendLayout()
        Me.SuspendLayout()
        '
        'Panel1
        '
        Me.Panel1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.Panel1.AutoScroll = True
        Me.Panel1.BackColor = System.Drawing.Color.LightPink
        Me.Panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.Panel1.Controls.Add(Me.PictureBox1)
        Me.Panel1.Location = New System.Drawing.Point(8, 40)
        Me.Panel1.Name = "Panel1"
        Me.Panel1.Size = New System.Drawing.Size(292, 276)
        Me.Panel1.TabIndex = 1
        '
        'PictureBox1
        '
        Me.PictureBox1.Location = New System.Drawing.Point(0, 0)
        Me.PictureBox1.Name = "PictureBox1"
        Me.PictureBox1.Size = New System.Drawing.Size(184, 128)
        Me.PictureBox1.TabIndex = 0
        Me.PictureBox1.TabStop = False
        '
        'Label1
        '
        Me.Label1.Location = New System.Drawing.Point(8, 8)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(296, 24)
        Me.Label1.TabIndex = 2
        Me.Label1.Text = "Label1"
        Me.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
        '
        'Timer1
        '
        Me.Timer1.Interval = 25
        '
        'NotifyIcon1
        '
        Me.NotifyIcon1.Text = "RubberBand Screen Capture Demo"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(312, 326)
        Me.Controls.Add(Me.Label1)
        Me.Controls.Add(Me.Panel1)
        Me.Name = "Form1"
        Me.Text = "RubberBand Screen Capture Demo"
        Me.Panel1.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Enum HotKeyModifiers
        None = &H0
        Alt = &H1
        Control = &H2
        Shift = &H4
        Windows = &H8
    End Enum
    Private Const SRCCOPY = &HCC0020
    Private Declare Function CreateDC Lib "gdi32" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, ByVal lpInitData As String) As Integer
    Private Declare Function CreateCompatibleDC Lib "GDI32" (ByVal hDC As Integer) As Integer
    Private Declare Function CreateCompatibleBitmap Lib "GDI32" (ByVal hDC As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer) As Integer
    Private Declare Function SelectObject Lib "GDI32" (ByVal hDC As Integer, ByVal hObject As Integer) As Integer
    Private Declare Function BitBlt Lib "GDI32" (ByVal hDestDC As Integer, ByVal X As Integer, ByVal Y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC As Integer, ByVal SrcX As Integer, ByVal SrcY As Integer, ByVal Rop As Integer) As Integer
    Private Declare Function DeleteObject Lib "GDI32" (ByVal hObj As Integer) As Integer
    Private Declare Function DeleteDC Lib "GDI32" (ByVal hDC As Integer) As Integer
    Private Declare Function RegisterHotKey Lib "user32" (ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Boolean
    Private Declare Function UnregisterHotKey Lib "user32" (ByVal hWnd As IntPtr, ByVal id As Integer) As Boolean

    Private Declare Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" (ByVal hWnd As IntPtr, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As IntPtr
    Private Declare Function GetSystemDirectory Lib "kernel32.dll" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Integer

    Private startX As Integer
    Private startY As Integer
    Private lastX As Integer
    Private lastY As Integer
    Private curX As Integer
    Private curY As Integer
    Private boxDrawn As Boolean = False
    Private hotKeySet As Boolean = False
    Private capturing As Boolean = False

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        RegisterHotKey(HotKeyModifiers.None, Keys.F9)
        If Not hotKeySet Then
            Label1.Text = "Unable to Set Hotkey F9"
            MsgBox("Unable to Set Hotkey F9")
        Else
            Label1.Text = "Press F9 to Start/Stop area selection"
        End If
    End Sub

    Private Function GetScreen(ByVal X As Integer, ByVal Y As Integer, ByVal Width As Integer, ByVal Height As Integer) As Bitmap
        Dim hDeskDC As Integer
        Dim hTempDC As Integer
        Dim hBitmap As Integer
        Dim hTempBmp As Integer
        Dim desktopArea As Bitmap

        hDeskDC = CreateDC("DISPLAY", "", "", "")
        If hDeskDC Then
            hTempDC = CreateCompatibleDC(hDeskDC)
            If hTempDC Then
                hBitmap = CreateCompatibleBitmap(hDeskDC, Width, Height)
                If hBitmap Then
                    hTempBmp = SelectObject(hTempDC, hBitmap)
                    BitBlt(hTempDC, 0, 0, Width, Height, hDeskDC, X, Y, SRCCOPY)
                    desktopArea = Bitmap.FromHbitmap(New IntPtr(hBitmap))
                    DeleteObject(SelectObject(hTempDC, hTempBmp))
                End If
                DeleteDC(hTempDC)
            End If
            DeleteDC(hDeskDC)
        End If
        Return desktopArea
    End Function

    Public Sub RegisterHotKey(ByVal mods As Integer, ByVal key As Integer)
        If hotKeySet Then
            UnregisterHotKey()
        End If
        hotKeySet = RegisterHotKey(Me.Handle, 0, mods, key)
    End Sub

    Public Sub UnRegisterHotkey()
        If hotKeySet Then
            hotKeySet = Not UnregisterHotKey(Me.Handle, 0)
        End If
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_HOTKEY As Integer = &H312

        Select Case m.Msg
            Case WM_HOTKEY
                hotKeyPressed()

        End Select
        MyBase.WndProc(m)
    End Sub

    Private Sub hotKeyPressed()
        If Not capturing Then
            capturing = True
            boxDrawn = False
            startX = Cursor.Position.X
            startY = Cursor.Position.Y
            lastX = startX
            lastY = startY
            Timer1.Enabled = True
        Else
            capturing = False
            Timer1.Enabled = False
            If boxDrawn Then
                ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, lastX - startX, lastY - startY), Color.Black, FrameStyle.Dashed)
                PictureBox1.Image = GetScreen(Math.Min(startX, curX), Math.Min(startY, curY), Math.Abs(curX - startX), Math.Abs(curY - startY))
                PictureBox1.Width = PictureBox1.Image.Width
                PictureBox1.Height = PictureBox1.Image.Height
            End If
        End If
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        If capturing Then
            curX = Cursor.Position.X
            curY = Cursor.Position.Y
            If curX <> lastX Or curY <> lastY Then
                If Not boxDrawn Then
                    boxDrawn = True
                    ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, curX - startX, curY - startY), Color.Black, FrameStyle.Dashed)
                Else
                    ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, lastX - startX, lastY - startY), Color.Black, FrameStyle.Dashed)
                    ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, curX - startX, curY - startY), Color.Black, FrameStyle.Dashed)
                End If
                lastX = curX
                lastY = curY
            End If
        End If
    End Sub

    Private Sub Form1_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.SizeChanged
        If Me.WindowState = FormWindowState.Minimized Then
            If Not (NotifyIcon1.Icon Is Nothing) Then
                Me.Hide()
                NotifyIcon1.Visible = True
            End If
        End If
    End Sub

    Private Sub NotifyIcon1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles NotifyIcon1.DoubleClick
        NotifyIcon1.Visible = False
        Me.Show()
        Me.WindowState = FormWindowState.Normal
    End Sub

    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        UnregisterHotKey()
    End Sub

End Class
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now