# VBForums CodeBank > CodeBank - Visual Basic .NET >  Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls

## gigemboy

Here is a class that contains very easy methods to get screen captures. It is not code originally written by me, it was actually found Here. It was originally written in C#, and there was supposedly a VB.NET example in there, however it just looked as if it was ran through some code converter that didn't work. I cleaned it up in order for it to work in .NET, replaced all the API declarations with the correct working ones, and even added a CaptureDeskTopRectangle function to it for desktop regions.

The file has its own namespace, "ScreenShot", which includes three seperate classes:

ScreenCapture - Main class, contains functions for obtaining the actual images
GDI32 = Helper Class with various GDI Functions that are used
USER32 - Helper Class with various User32 Functions used

The ScreenCapture has five exposed functions and methods that enables you to get captures:

CaptureWindow - grabs image of object by its handle
CaptureScreen - grabs image of entire screen
CaptureWindowToFile - captures image of object by its handle straight to file
CaptureScreenToFile - captures image of screen straight to file
CaptureDesktopRectangle - captures desktop region by a passed in rectangle

    ***.NET 2005 has a .CopyFromScreen method in the Graphics class that allows you to get a desktop region, however, there is no way in 2003, which is why CaptureDesktopRectangle was needed...


Sample code showing how to use each method is below, the class is available for download at the end of the post.

VB Code:
Dim SC As New ScreenShot.ScreenCapture
         'grabs image of object handle (in this case, the form)
        Dim MyWindow As Image = SC.CaptureWindow(Me.Handle)
        
        'grabs image of entire desktop
        Dim MyDesktop As Image = SC.CaptureScreen
        
        'captures entire desktop straight to file
        SC.CaptureScreenToFile("c:\desktop2.jpg", Imaging.ImageFormat.Jpeg)
         'captures image of object handle (in this case, the form) straight to file
        SC.CaptureWindowToFile(Me.Handle, "c:\window2.jpg", Imaging.ImageFormat.Jpeg)
         'returns bitmap of region of desktop by passing in a rectangle
        Dim MyBitMap As Bitmap = SC.CaptureDeskTopRectangle(New Rectangle(Me.Location.X, Me.Location.Y, _
                                     Me.Width, Me.Height), Me.Width, Me.Height)
        MyBitMap.Save("c:\desktopregion.jpg", Imaging.ImageFormat.Jpeg)
        'above example gets rectangle of form that it is called in, you can get 
        'desktop by calling me.hide before the actual function call in order to 
        'get the desktop that is in the bounds of the form (handy when using a 
        'transparent Form or control in order to make a "viewfinder" for the capture...)
        'You can pass in any rectangle you want, this was so you can see how
        'it works...
Happy coding!   :Smilie:

----------


## maged

this is very useful 

thank you

rgds

----------


## gjon

Very neat, anyone make a windows app or a console app for this yet using this? 
I'd love to check it out.

----------


## gigemboy

EZScreenCap in my sig was made using it, nothing fancy and I didn't spend a lot of time doing it. Just sort of a proof of concept...

----------


## lidds

gigemboy,

Thanks for the code it is exacually what I have been looking for, however I am having a really hard time trying to create the code to allow the user to specify a region using mouse clicks.  I noticed in your EZScreenCap you have this ability and I was wondering if you would be able to help with the code that you used to acheive this.

Thanks inadvance

Simon

----------


## gigemboy

Using mouse clicks?? You mean the "Viewfinder"? Its just a transparent panel on a form, and it gets the bounds of panel when you capture it (after first hiding the form so it doesnt capture the form). The last code above describes it, although in the example it uses the form bounds.

----------


## mb2ai

when i click on the attatchment, a html web page comes up and all the code is like a textfile, is it meant to be like this, or is it an error.
Ideally id like to see how the application works, so I can use it for somthing.

MB

----------


## gigemboy

Are you talking about the Class attachment? Its just a file.. if it doesn't ask you to save then your browser is set to do something automatically with that file. Just right click the link and choose "save target as" or something. If you just see the text, just save that file as a .VB file and add it to your project...

----------


## mb2ai

wow its wicked!
v good

----------


## steffanp

Hi i have been using your class but i have little problem. I have this loop that takes a sceenshot, and then analyzes it. every time i use the class to take a screenshot, it filles my RAM with 6 extra megabytes (and it takes approx. 1 screenshot every second. So after aboute 1 minute, it uses approx 700 MB RAM :S:S.. why?


VB Code:
Dim SIR As New SteffansImageRecognizion()
        Dim SC As New ScreenShot.ScreenCapture
         Dim ColorBuffer As System.Drawing.Color
        Dim BitmapBuffer As System.Drawing.Bitmap
        Dim ImageBuffer As System.Drawing.Image
         While (True)
            BitmapBuffer = SC.CaptureDeskTopRectangle(New System.Drawing.Rectangle(0, 0, 0, 0), 1000, 700)
             ' Lots of code..
         End While

----------


## gigemboy

Then I assume its something in your code that is not being disposed of properly, whatever you are doing in it. I don't believe its a problem in the class. I tested EZScreenCap, which uses the class, and after taking a few snapshots, the memory increased by about 10-20 megabytes after taking a few quick snapshots in rapid succession, but after a short time, it goes back down to about where it was before (a little higher just because of the extra graphics that it has to display in the listview), after the garbage collector does its job and cleans up...

If you want to get help with your code, then feel free to post it, but please create a new thread in the regular VB.NET section for it if you desire.

----------


## WoZ83

Hi, I need to know how I can use your code on pocket pc using compact framework?!
Thanks a lot.

----------


## Giraffe Frenzy

gigemboy,

Do you know of a way to capture an image on a remote machine? Assuming that you have the correct permissions to do so.

----------


## RupinderSamra

this screen capture is great but i was wondering is it possible to take screen shots of the window when the window is minimised?

----------


## zhshqzyc

I get three errors by using the example.
Declaration expected.

Imports System.Windows.Forms

Public Class Form1
    Dim SC As New ScreenShot.ScreenCapture

    'grabs image of object handle (in this case, the form)
    Dim MyWindow As Image = SC.CaptureWindow(Me.handle)

    'grabs image of entire desktop
    Dim MyDesktop As Image = SC.CaptureScreen

    'captures entire desktop straight to file
        SC.CaptureScreenToFile("c:\desktop2.jpg", Imaging.ImageFormat.Jpeg)* 'Here SC*

    'captures image of object handle (in this case, the form) straight to file
        SC.CaptureWindowToFile(Me.Handle, "c:\window2.jpg", Imaging.ImageFormat.Jpeg) 'Here SC

    'returns bitmap of region of desktop by passing in a rectangle
    Dim MyBitMap As Bitmap = SC.CaptureDeskTopRectangle(New Rectangle(Me.Location.X, Me.Location.Y, _
    Me.Width, Me.Height), Me.Width, Me.Height)
        MyBitMap.Save("c:\desktopregion.jpg", Imaging.ImageFormat.Jpeg) *'Here MyBitMap*
    'above example gets rectangle of form that it is called in, you can get 
    'desktop by calling me.hide before the actual function call in order to 
    'get the desktop that is in the bounds of the form (handy when using a
    'transparent Form or control in order to make a "viewfinder" for the capture...)
    'You can pass in any rectangle you want, this was so you can see how
    'it works... 
End Class

Anybody can help?

Thanks

----------


## chris128

very useful, thanks  :Smilie:

----------


## Bumbling Intern

I am currently having trouble with trying to implement the code.


```
Imports System
Imports System.Diagnostics
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports DirectShowLib
Imports System.Runtime.InteropServices.ComTypes
Imports System.ComponentModel

Namespace Capture_The_Webcam


    Public Class Form1
        Inherits System.Windows.Forms.Form
'webcam code from http://www.codeproject.com/KB/audio-video/WebcamUsingDirectShowNET.aspx
'webcam feed is handled by picturebox1
        Public Class ScreenCapture
            Dim SC As New ScreenShot.ScreenCapture

            'grabs image of object handle (in this case, the form)
            Dim MyWindow As Image = SC.CaptureWindow(Capture2.Capture_The_Webcam.Form1.PictureBox1.Handle)
            'Dim SC As ScreenCapture.Screenshot

            Public SRCCOPY As Integer = &HCC0020
            ' BitBlt dwRop parameter
            Declare Function BitBlt Lib "gdi32.dll" ( _
                ByVal hDestDC As IntPtr, _
                ByVal x As Int32, _
                ByVal y As Int32, _
                ByVal nWidth As Int32, _
                ByVal nHeight As Int32, _
                ByVal hSrcDC As IntPtr, _
                ByVal xSrc As Int32, _
                ByVal ySrc As Int32, _
                ByVal dwRop As Int32) As Int32

            Declare Function CreateCompatibleBitmap Lib "gdi32.dll" ( _
                ByVal hdc As IntPtr, _
                ByVal nWidth As Int32, _
                ByVal nHeight As Int32) As IntPtr

            Declare Function CreateCompatibleDC Lib "gdi32.dll" ( _
                ByVal hdc As IntPtr) As IntPtr

            Declare Function DeleteDC Lib "gdi32.dll" ( _
                ByVal hdc As IntPtr) As Int32

            Declare Function DeleteObject Lib "gdi32.dll" ( _
                ByVal hObject As IntPtr) As Int32

            Declare Function SelectObject Lib "gdi32.dll" ( _
                ByVal hdc As IntPtr, _
                ByVal hObject As IntPtr) As IntPtr
        End Class 'GDI32
        '/ Helper class containing User32 API functions
        


        Public Class User32
          
            <StructLayout(LayoutKind.Sequential)> _
            Public Structure RECT
                Public left As Integer
                Public top As Integer
                Public right As Integer
                Public bottom As Integer
            End Structure 'RECT
            '/ Helper class containing Gdi32 API functions
            Public Class GDI32
                Public SRCCOPY As Integer = &HCC0020
                ' BitBlt dwRop parameter
                Declare Function BitBlt Lib "gdi32.dll" ( _
                    ByVal hDestDC As IntPtr, _
                    ByVal x As Int32, _
                    ByVal y As Int32, _
                    ByVal nWidth As Int32, _
                    ByVal nHeight As Int32, _
                    ByVal hSrcDC As IntPtr, _
                    ByVal xSrc As Int32, _
                    ByVal ySrc As Int32, _
                    ByVal dwRop As Int32) As Int32

                Declare Function CreateCompatibleBitmap Lib "gdi32.dll" ( _
                    ByVal hdc As IntPtr, _
                    ByVal nWidth As Int32, _
                    ByVal nHeight As Int32) As IntPtr

                Declare Function CreateCompatibleDC Lib "gdi32.dll" ( _
                    ByVal hdc As IntPtr) As IntPtr

                Declare Function DeleteDC Lib "gdi32.dll" ( _
                    ByVal hdc As IntPtr) As Int32

                Declare Function DeleteObject Lib "gdi32.dll" ( _
                    ByVal hObject As IntPtr) As Int32

                Declare Function SelectObject Lib "gdi32.dll" ( _
                    ByVal hdc As IntPtr, _
                    ByVal hObject As IntPtr) As IntPtr
            End Class 'GDI32
            '/ Creates an Image object containing a screen shot of a specific window
            Public Function CaptureWindow(ByVal handle As IntPtr) As Image
                Dim SRCCOPY As Integer = &HCC0020
                ' get te hDC of the target window
                Dim hdcSrc As IntPtr = User32.GetWindowDC(handle)
                ' get the size
                Dim windowRect As New User32.RECT
                User32.GetWindowRect(handle, windowRect)
                Dim width As Integer = 640
                Dim height As Integer = 480
                ' create a device context we can copy to
                Dim hdcDest As IntPtr = GDI32.CreateCompatibleDC(hdcSrc)
                ' create a bitmap we can copy it to,
                ' using GetDeviceCaps to get the width/height
                Dim hBitmap As IntPtr = GDI32.CreateCompatibleBitmap(hdcSrc, width, height)
                ' select the bitmap object
                Dim hOld As IntPtr = GDI32.SelectObject(hdcDest, hBitmap)
                ' bitblt over
                GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, SRCCOPY)
                ' restore selection
                GDI32.SelectObject(hdcDest, hOld)
                ' clean up 
                GDI32.DeleteDC(hdcDest)
                User32.ReleaseDC(handle, hdcSrc)

                ' get a .NET image object for it
                Dim img As Image = Image.FromHbitmap(hBitmap)
                ' free up the Bitmap object
                GDI32.DeleteObject(hBitmap)

                Return img
            End Function 'CaptureWindow
            
            Function Function1()
                ''captures image of object handle (in this case, the form) straight to file
 SC.CaptureWindowToFile(Capture2.Capture_The_Webcam.Form1.PictureBox1.Handle, "c:\ProgramFiles\ImgCap\Tmp.bmp", Imaging.ImageFormat.BMP)
                Return 0
            End Function

            Declare Function GetDesktopWindow Lib "user32.dll" () As IntPtr

            Declare Function GetWindowDC Lib "user32.dll" ( _
                ByVal hwnd As IntPtr) As IntPtr

            Declare Function ReleaseDC Lib "user32.dll" ( _
                ByVal hwnd As IntPtr, _
                ByVal hdc As IntPtr) As Int32

            Declare Function GetWindowRect Lib "user32.dll" ( _
                ByVal hwnd As IntPtr, _
                ByRef lpRect As RECT) As Int32
        End Class

        Private Sub ButtonX_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonX.Click

            Dim SecondsNow As Integer = Second(Now)
            While Second(Now) < 1 + SecondsNow
                ButtonX.Enabled = False
            End While

            Dim test As New User32
            test.Function1()

        End Sub
    End Class
End Namespace
```

I keep getting the error that Screenshot.Screencapture is not defined. Any ideas?
THanks

----------


## Bumbling Intern

Hi,

After some fiddling around, the problem was fixed by putting all the screen capture class code BEFORE the Capture_the_Webcam code.

Much better now, great code it was very helpful. Thank you  :wave:

----------


## mcManiac

Hi guys, this code works but what i'm trying to do is get this code to take the picture and set it in a different directory .. anyone got an answer?



```
        Dim SC As New ScreenShot.ScreenCapture
        Dim windowList As List(Of Game.WindowInfo) = Game.GetWindowList()
        Dim screenshotname As String
        screenshotname = grpInfo.Text & ".jpg"
        SC.CaptureWindowToFile(DirectCast(windowList(lstGame.SelectedIndex), Game.WindowInfo).Handle, screenshotname, Imaging.ImageFormat.Jpeg)
```

----------


## BrailleSchool

> Hi guys, this code works but what i'm trying to do is get this code to take the picture and set it in a different directory .. anyone got an answer?
> 
> 
> 
> ```
>         Dim SC As New ScreenShot.ScreenCapture
>         Dim windowList As List(Of Game.WindowInfo) = Game.GetWindowList()
>         Dim screenshotname As String
>         screenshotname = grpInfo.Text & ".jpg"
> ...


where you have screenshotname, what about if you add the path you want to save the image to and then specify grpInfo.Text & ".jpg"

----------


## SL1509

Hi,
very good code, but i have a problem with my second monitor. On this screen the created screenshots are black.
Can anybody help?

Thanks a lot.

----------


## filthy_mcnasty

To the original poster: THANKS! This is cool stuff you've passed along and it saved me some time for sure.

To the last poster: I had a similar problem. I have lots of monitors and was getting nowhere trying to get a screenshot of all of them at the same time.

GetDesktopWindow() API call will return the handle only for the primary video display, not the entire screen output.... booooo MS!!...... so this code will only take a screenshot of ONE monitor as is.


For the original poster: Instead of using User32.GetDesktopWindow() I found the REAL Window that represents the desktop and modified your code so it will work across ALL screens.



```
            Dim base As IntPtr = User32.FindWindow("Progman", "Program Manager")
            Dim b2 As IntPtr = User32.FindWindowEx(base, vbNullString, "SHELLDLL_DefView", vbNullString)
            b2 = User32.FindWindowEx(b2, vbNullString, "SysListView32", vbNullString)
            
            Return CaptureWindow(b2)
```

Before, the function was just Return CaptureWindow(User32.GetDesktopWindow())

also added:
            <Runtime.InteropServices.DllImport("User32.dll")> _
                Public Shared Function FindWindowEx(ByVal hwndParent As IntPtr, ByVal hwndChild As IntPtr, ByVal className As String, ByVal caption As String) As IntPtr
            End Function

            <Runtime.InteropServices.DllImport("User32.dll")> _
                Public Shared Function FindWindow(ByVal className As String, ByVal caption As String) As IntPtr
            End Function


I'm pretty sure this behavior is consistent across all versions of Windows but I've only tested this in XP. 

Anyways, hope this saves someone else a headache, thanks again.

----------


## NonProgrammer

Can somebody update the code to work with Microsoft Visual Basic 2008 for me? (And Post it for me too please!)

----------


## farooqaaa

I really want this class in C#. I've found one online but the "DesktopRectangle()" method isn't there.

Is it possible to get this class in C#?

Thanks

----------


## farooqaaa

A clone of this one is available for C# here:
http://www.farooqazam.net/screen-cap...ss-for-c-sharp

 :Smilie:

----------


## Brian M.

Very easy to use class, thanks alot! I spent hours trying to capture this control with no luck, until I added this class. Here is an app I made that uses it to capture the control that is drawn on.

Lite Brite

----------


## youngaj

> Can somebody update the code to work with Microsoft Visual Basic 2008 for me? (And Post it for me too please!)


I just stumbled on this code and it seems perfect, if I could only get it to work.  I'm running VS 2008 as well and I'm running into several problems.  
Me.Handle is not recognizedMe.Location.X is not recognizedetcAlso I'm getting an error when I try to save the image to a file

I've attached my code behind

----------


## ramesh017

Hi 

im new to VB.NET... Can u pls tel me how to implement the code?? i mean form ? coz i have created a new form and pasted the cod ein designer.. but its showing some error and the form was not loading:-(

----------


## Brian M.

Hey ramesh, do you know what a class is? This is not code you can paste into a form, you have to make calls to the class from your form code.

*Classes*
MSDN-vb classesWikipedia-classes

----------


## ramesh017

Cool... I need a piece of code which will capture screen shot of the form.. Can u help me to get it form this code!!

----------


## Brian M.

First you must add the SCapture.vb class file to your project in the solution explorer. Then you have to make a button on your form so you can have an event to capture the form picture. In the button's click event handler add this code:



```
        Dim filePath As String = My.Computer.FileSystem.SpecialDirectories.Desktop & "\myFormImage.png"

        Try
            Dim img As Image = SCapture.Control(Me.Handle, False)
            img.Save(filePath, Drawing.Imaging.ImageFormat.Png)
        Catch ex As Exception
            MessageBox.Show("Failed to capture the control!" _
            & Environment.NewLine & ex.Message, "Capture Error!", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
```

Then when you click the button you put this code in, it should save a png image of your form to your desktop.

----------


## ramesh017

I did the same what u told.. But its showing soem error:-(

Also it is saying that Name 'screencapture' is not declared

----------


## ramesh017

```
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Dim filePath As String = "C:\Documents and Settings\175943\Desktop\mypicture.png"
        Try
            Dim img As Image = screencapture.Control(Me.Handle, False)

            img.Save(filePath, Drawing.Imaging.ImageFormat.Png)
        Catch ex As Exception
            MessageBox.Show("Failed to capture the control!" _
            & Environment.NewLine & ex.Message, "Capture Error!", _
            MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub Capture_window_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Capture_window.CheckedChanged
        If Capture_window.Checked Then
            Me.Opacity = 0.6
        Else
            Me.Opacity = 1

        End If
        If Capture_window.Checked And Doc_Button.Checked Then
            Button2.Visible = False
            Button1.Visible = False
            Button3.Visible = True
        ElseIf Capture_window.Checked And Img_Button.Checked Then
            Button2.Visible = False
            Button1.Visible = False
            Button3.Visible = True
        ElseIf Doc_Button.Checked = True Then
            Button3.Visible = False
            Button2.Visible = True
            Button3.ForeColor = Color.Blue
        End If

    End Sub

    Public Class screencapture

        Public Function CaptureScreen() As Image
            Return CaptureWindow(User32.GetDesktopWindow())
        End Function 'CaptureScreen

        '/ Creates an Image object containing a screen shot of a specific window
        Public Function CaptureWindow(ByVal handle As IntPtr) As Image
            Dim SRCCOPY As Integer = &HCC0020
            ' get te hDC of the target window
            Dim hdcSrc As IntPtr = User32.GetWindowDC(handle)
            ' get the size
            Dim windowRect As New User32.RECT
            User32.GetWindowRect(handle, windowRect)
            Dim width As Integer = windowRect.right - windowRect.left
            Dim height As Integer = windowRect.bottom - windowRect.top
            ' create a device context we can copy to
            Dim hdcDest As IntPtr = GDI32.CreateCompatibleDC(hdcSrc)
            ' create a bitmap we can copy it to,
            ' using GetDeviceCaps to get the width/height
            Dim hBitmap As IntPtr = GDI32.CreateCompatibleBitmap(hdcSrc, width, height)
            ' select the bitmap object
            Dim hOld As IntPtr = GDI32.SelectObject(hdcDest, hBitmap)
            ' bitblt over
            GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, SRCCOPY)
            ' restore selection
            GDI32.SelectObject(hdcDest, hOld)
            ' clean up 
            GDI32.DeleteDC(hdcDest)
            User32.ReleaseDC(handle, hdcSrc)

            ' get a .NET image object for it
            Dim img As Image = Image.FromHbitmap(hBitmap)
            ' free up the Bitmap object
            GDI32.DeleteObject(hBitmap)

            Return img
        End Function 'CaptureWindow
        '/ Captures a screen shot of a specific window, and saves it to a file
        Public Sub CaptureWindowToFile(ByVal handle As IntPtr, ByVal filename As String, ByVal format As ImageFormat)
            Dim img As Image = CaptureWindow(handle)
            img.Save(filename, format)
        End Sub 'CaptureWindowToFile
        '/ Captures a screen shot of the entire desktop, and saves it to a file
        Public Sub CaptureScreenToFile(ByVal filename As String, ByVal format As ImageFormat)
            Dim img As Image = CaptureScreen()
            img.Save(filename, format)
        End Sub 'CaptureScreenToFile
        Public Function CaptureDeskTopRectangle(ByVal CapRect As Rectangle, ByVal CapRectWidth As Integer, ByVal CapRectHeight As Integer) As Bitmap
            '/ Returns BitMap of the region of the desktop, similar to CaptureWindow, but can be used to 
            '/ create a snapshot of the desktop when no handle is present, by passing in a rectangle 
            '/ Grabs snapshot of entire desktop, then crops it using the passed in rectangle's coordinates
            Dim SC As New MainWindow.screencapture
            Dim bmpImage As New Bitmap(SC.CaptureScreen)
            Dim bmpCrop As New Bitmap(CapRectWidth, CapRectHeight, bmpImage.PixelFormat)
            Dim recCrop As New Rectangle(CapRect.X, CapRect.Y, CapRectWidth, CapRectHeight)
            Dim gphCrop As Graphics = Graphics.FromImage(bmpCrop)
            Dim recDest As New Rectangle(0, 0, CapRectWidth, CapRectHeight)
            gphCrop.DrawImage(bmpImage, recDest, recCrop.X, recCrop.Y, recCrop.Width, _
              recCrop.Height, GraphicsUnit.Pixel)
            Return bmpCrop
        End Function
        '/ Helper class containing Gdi32 API functions
        Private Class GDI32
            Public SRCCOPY As Integer = &HCC0020
            ' BitBlt dwRop parameter
            Declare Function BitBlt Lib "gdi32.dll" ( _
                ByVal hDestDC As IntPtr, _
                ByVal x As Int32, _
                ByVal y As Int32, _
                ByVal nWidth As Int32, _
                ByVal nHeight As Int32, _
                ByVal hSrcDC As IntPtr, _
                ByVal xSrc As Int32, _
                ByVal ySrc As Int32, _
                ByVal dwRop As Int32) As Int32

            Declare Function CreateCompatibleBitmap Lib "gdi32.dll" ( _
                ByVal hdc As IntPtr, _
                ByVal nWidth As Int32, _
                ByVal nHeight As Int32) As IntPtr

            Declare Function CreateCompatibleDC Lib "gdi32.dll" ( _
                ByVal hdc As IntPtr) As IntPtr

            Declare Function DeleteDC Lib "gdi32.dll" ( _
                ByVal hdc As IntPtr) As Int32

            Declare Function DeleteObject Lib "gdi32.dll" ( _
                ByVal hObject As IntPtr) As Int32

            Declare Function SelectObject Lib "gdi32.dll" ( _
                ByVal hdc As IntPtr, _
                ByVal hObject As IntPtr) As IntPtr
        End Class 'GDI32
        '/ Helper class containing User32 API functions
        Public Class User32
            <StructLayout(LayoutKind.Sequential)> _
            Public Structure RECT
                Public left As Integer
                Public top As Integer
                Public right As Integer
                Public bottom As Integer
            End Structure 'RECT

            Declare Function GetDesktopWindow Lib "user32.dll" () As IntPtr

            Declare Function GetWindowDC Lib "user32.dll" ( _
                ByVal hwnd As IntPtr) As IntPtr

            Declare Function ReleaseDC Lib "user32.dll" ( _
                ByVal hwnd As IntPtr, _
                ByVal hdc As IntPtr) As Int32

            Declare Function GetWindowRect Lib "user32.dll" ( _
                ByVal hwnd As IntPtr, _
                ByRef lpRect As RECT) As Int32

        End Class 'User32
    End Class 'ScreenCapture
```


Refer the code above.. 

I got an error that control is not a member of 'mainwindow .screencapture'.

----------


## Brian M.

You must add the class file to your solution explorer. You can't add the class code to your form. You can either right click your project in solution explorer or you can use the add item menu item. You pick add existing item and navigate to where your class file is stored then select it to add it to your project. Then remove the class code from your form code. See attached picture for an example.

----------


## ramesh017

Hey Brian,

Thanks for your effort to teach me!! I have doen the same thing.. But its showing lot of errors!!

PFA

----------


## Brian M.

What version of Visual Studios are you using? This class is written for 2005.

----------


## sansharam

Hi all

Can anybody help me??... 

Dear all 

I have an application which provides some data in datagrid ... by right click i can copy that and past that in to a text file..... 

my quest is can i get this process done by vb.net code

Please help me

thanks in advance

sansharam
 :Smilie:

----------


## Dario

Using this screencapture class win *winxp*, and it does what i want.  :Thumb:  very easy to use.

*However on Windows 7 pc's (32 or 64 bit) - i get black image...* :Frown: 

Any solutions for this win7 issue?

Just to add: the app i am making is SERVICE BASED & currently it works on WinXP, when installed on Win7, just black image.

----------


## 03myersd

Excellent class! So useful! Hard to believe .NET doesnt have this built in. Great solution though!

----------


## Dario

> Using this screencapture class win *winxp*, and it does what i want.  very easy to use.
> 
> *However on Windows 7 pc's (32 or 64 bit) - i get black image...*
> 
> Any solutions for this win7 issue?
> 
> Just to add: the app i am making is SERVICE BASED & currently it works on WinXP, when installed on Win7, just black image.


Grrr been googling for 2 weeks on this issue, and all i can find is that some people have the same problem, and that windows 7 gdi/win32 api has changed a great deal since introduction of VISTA and onwards, windows 7.

http://stackoverflow.com/questions/1...indows-service

Going crazy.. :Cry:  :Eek Boom:

----------


## rongage

I am having a weird problem and was hoping someone could offer a pointer or two...
Consider the following sub:


```
    Private Sub _timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim sc As New ScreenShot.ScreenCapture
        Debug.Print("Tick: " & Now)
        If rdp.Count > 0 Then
            For Each r As _rdp In rdp
                r.pic.Image = sc.CaptureWindow(r.rdp.Handle).GetThumbnailImage(160, 120, Nothing, Nothing)

            Next
        End If
        sc = Nothing
    End Sub
```

It triggers every 3 seconds, refreshing the r.pic.image with a screen cap from r.rdp.handle.  Pretty straight forward, right?  Well, except what is happening is that the resulting image is re-shrunk every iteration so the first image is 160x120, the second is much smaller, the third - even smaller, the fourth is basically a single pixel and from 5 on it is nothing.

If I run without GetThumbnailImage(), the image in the picturebox moves every iteration by roughly 30 pixels in both X and Y.

Anyone ever run into this before?

HELP!

Ron

----------


## Cimperiali

> replaced all the API declarations with the correct working ones


 Nice job. I stepped in looking to remember how we used to do it in previous versions, and then I remembred the main matter: using unmanaged code (=calling Api directly somewhere in code) steal one of the main goals of a framework like Net: portability.
Indeed there was not other way to do it in 1.0 and, i do belive, in 1.1. since 2.0 we all are a bit more lucky and we can grab screen easier in a managed mode. 
an easy example - nothing to compare with the wonderful job of  gigemboy - :
a form ("frmCapture"), two buttons ("btnWholeScreen", "btnThisForm")  a pictureBox ("picCaptured") to show result is acquired (or you can save to a file).



```
Public Class frmCapture
    Private Sub frmCapture_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        picCaptured.SizeMode = PictureBoxSizeMode.StretchImage
    End Sub
    Private Sub btnWholeScreen_Click(sender As System.Object, e As System.EventArgs) Handles btnWholeScreen.Click
        Dim Bmp As Bitmap = GetPicture(My.Computer.Screen.Bounds, New Point(0, 0))
        'Bmp.Save("C:\CapturedScreen.png")
        picCaptured.Image = Bmp
    End Sub

    Private Sub btnThisForm_Click(sender As System.Object, e As System.EventArgs) Handles btnThisForm.Click
        Dim Bmp As Bitmap = GetPicture(Me.Bounds, New Point(Me.Left, Me.Top))
        'Bmp.Save("C:\CapturedForm.png")
        picCaptured.Image = Bmp

    End Sub
    Private Function GetPicture(bounds As Rectangle, upleftSource As Point) As Bitmap
        Dim retBmp As New Bitmap(bounds.Width, bounds.Height)
        Dim G As Graphics = Graphics.FromImage(retBmp)
        G.CopyFromScreen(upleftSource, New Point(0, 0), bounds.Size, CopyPixelOperation.SourceCopy)
        G.Dispose()
        Return retBmp
    End Function
```

----------


## schrady

I can easily get the form or whole desktop captured. What I'm having an issue with is being able to select the area to capture with the mouse. I'm very surprised that hasn't been covered in this thread.

Can someone please post code to capture the screen that you select by drawing a box with the mouse?

Thanks in advance

Schrady

----------


## Cimperiali

A trick to capture a region could be: make the whole screen capture, then show that picture and let user use the mouse to get a portion of it. It seems to me PickPick (a free utility to do that job among others) uses that logic.

----------


## moti barski

screen capture code :



```
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim screenBounds = Screen.PrimaryScreen.Bounds
        Dim screenShot As New Bitmap(screenBounds.Width, screenBounds.Height)
        Using g = Graphics.FromImage(screenShot)
            g.CopyFromScreen(screenBounds.Location, Point.Empty, screenBounds.Size)
        End Using
        PictureBox1.Image = screenShot
        'Dim filePath = IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.MyPictures, "ScreenShot.bmp")
        'screenShot.Save(filePath, Imaging.ImageFormat.Bmp)
    End Sub
End Class
```

----------


## clement52

If you want to use some screen recording software to help you record movement on screen, you should choose the right program. The one I used can help me capture whatever streaming video and audio files on screen with high quality, and it will also help me save it to standard video file. And you'll be able to upload your tutorial video to video sharing website or share with your friends.

----------


## mankowitz

This is a strange error:

I am using this library to capture the contents of a web browser which is in another window. 

First, I find the window using this:

        For Each p As Process In Process.GetProcesses
            If p.MainWindowTitle = "whatever" Then
                 handle = p.MainWindowHandle
        Next

I can then look at the image with this:

        Dim sc As New ScreenCapture
        Dim bmp As Bitmap = CType(sc.CaptureWindow(handle), Bitmap)

The odd thing is that the image I get is of a RECENT window state, but not the current state. For example, suppose I go to a web page with a form on it and click submit and then get a response, AND THEN run the code above. The resulting bmp contains an image of the screen from BEFORE I clicked submit. 

I am running vista. Any thoughts?

----------


## Troy Lundin

I have been using this for awhile and just recently I have decided to test the speed of it. I am capturing a window (480, 320) that runs at 60fps. I found using this test that, even though I capture twice immediately after each other, the captures are not always exactly the same. Below is the code I used. It's about as fast as I can make it.

Notice the two calls to CaptureWindowRegion. They happen right after each other. No other code or delays between them. 60fps means that each frame takes 16 milliseconds. This code finished an iteration in an average of 20 milliseconds, but most of that time is spent comparing the bitmaps.

My question is: Are there any updated function in the newest version of .NET that could speed this capturing process up? Any way to upgrade this code to be faster?

Stats for this code:
 - Iterations: 5000
 - Mismatches: 252
 - Mismatch Percent: 5.04
 - Time to complete: 104780.9931 (milliseconds)

Here is the test code I used.

vb Code:
Friend Sub test()
        While Loaded
             ' If the VBA hasn't been attached to yet, it has closed or the WRAM or IRAM are not set...
            If proc Is Nothing OrElse proc.HasExited Then
                For Each p As Process In Process.GetProcesses
                    If p.MainWindowTitle.Contains("VisualBoyAdvance") Then
                         ' Found VBA. Open it with full access.
                        proc = p
                        hWnd = p.MainWindowHandle
                        hProcess = OpenProcess(&H1F0FFF, False, p.Id)
                         Exit For
                    End If
                Next
                time = Date.Now ' Start time excluding time looking for the process.
            Else
                If cbCapture.Checked Then
                     ' Make we sill have the window handle then grab the screen.
                    If hWnd = IntPtr.Zero Then
                        hWnd = proc.MainWindowHandle
                    Else
                        bmptemp = New Bitmap(240, 160)
                        bmptemp2 = New Bitmap(240, 160)
                         ' Grab the screen twice.
                        bmpSrcBig = sc.CaptureWindowRegion(hWnd, New Rectangle(8, 50, 480, 320))
                        bmpSrcBig2 = sc.CaptureWindowRegion(hWnd, New Rectangle(8, 50, 480, 320))
                         ' Draw the screen grabs to another bitmap, shrinking them to normal size.
                        Using g As Graphics = Graphics.FromImage(bmptemp)
                            g.InterpolationMode = Drawing2D.InterpolationMode.Bilinear
                            g.DrawImage(bmpSrcBig, 0, 0, 240, 160)
                        End Using
                         Using g As Graphics = Graphics.FromImage(bmptemp2)
                            g.InterpolationMode = Drawing2D.InterpolationMode.Bilinear
                            g.DrawImage(bmpSrcBig2, 0, 0, 240, 160)
                        End Using
                         ' Lock the bits.
                        bmpDataA = bmptemp.LockBits(VBAScreenRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb)
                        bmpDataB = bmptemp2.LockBits(VBAScreenRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb)
                         ' Check if they are not identical.
                        Check()
                         ' Unlock the bits.
                        bmptemp.UnlockBits(bmpDataA)
                        bmptemp2.UnlockBits(bmpDataB)
                         ' Increase iteration, display percentage and check if we are finished.
                        SetText(Me, (mismatch / iteration) * 100 & " | " & Date.Now.Subtract(time).TotalMilliseconds)
                         If iteration = 5000 Then
                            sb = New StringBuilder
                            sb.Append("Iterations: ")
                            sb.AppendLine(iteration)
                            sb.Append("Mismatches: ")
                            sb.AppendLine(mismatch)
                            sb.Append("Mismatch Percent: ")
                            sb.AppendLine((mismatch / iteration) * 100)
                            sb.Append("Time to complete: ")
                            sb.Append(Date.Now.Subtract(time).TotalMilliseconds)
                            MessageBox.Show(sb.ToString)
                            Exit Sub
                        End If
                         iteration += 1
                    End If
                End If
            End If
        End While
    End Sub
     Friend Sub Check()
        For y1 As Int32 = 0 To 159
            For x1 As Int32 = 0 To 239
                 If Marshal.ReadInt32(bmpDataA.Scan0, (bmpDataA.Stride * y1) + (4 * x1)) <> _
                   Marshal.ReadInt32(bmpDataB.Scan0, (bmpDataB.Stride * y1) + (4 * x1)) Then
                    mismatch += 1
                    Exit Sub
                End If
             Next
        Next
    End Sub

----------


## mankowitz

Troy-

Does that code work for an INACTIVE window, one that is hidden behind another window?

----------


## Troy Lundin

> Troy-
> 
> Does that code work for an INACTIVE window, one that is hidden behind another window?


Yes.

----------


## WarrenW

Did you ever find a solution for Windows 7 saving it as a black image?

----------


## earthdog

I have 2 monitors and i am getting black capture from one of them (not the primary).

If i define a rectangle that spans from monitor 1 to monitor 2 i am getting black for the portion of the secondary monitor and the normal contents from the primary one.

What i have to do to the class to get correct results?

----------


## earthdog

I define the rectangle by :


vb Code:
myRect.Location = Me.Location        myRect.Height = Me.Height        myRect.Width = Me.Width

Me is a transparent form...

----------


## earthdog

it seems CaptureScreen gets only the primary screen...

Any way to capture all desktop?

----------


## Zapthus

Hi! First of all I just wanted to say thanks for this wonderful piece of code. There is one thing I'm having troubles, though. I am trying to take a take a screenshoot of a message box of a game, but for some reason it only takes a screenshoot of the game but ignores the message box. It works perfect on windows 7, but it does not work on windows XP.

Here's a picture: 

http://imageshack.us/photo/my-images...blewindow.png/

Any thoughts?

----------


## Zapthus

Also, if it helps... The problem also occurs whenever I disable Aero in Windows 7.

----------


## mainX

So what I need to get this working? pictureboxes? buttons?

----------


## toxinburn

The only way I have been able to get around getting black screenshots is to disable desktop composition by right clicking the exe and going to properties and ticking it then applying and saving, however in windows 8 this option is gone I hope that helps with users on win7 however is their a way with code to force an application in win8 to disable desktop composition?

----------

