College Station, TX Preferred Nickname: Gig Current Mood: Just Peachy Turnons: String Manipulation
Posts
4,495
Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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)
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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.
College Station, TX Preferred Nickname: Gig Current Mood: Just Peachy Turnons: String Manipulation
Posts
4,495
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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.
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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.
College Station, TX Preferred Nickname: Gig Current Mood: Just Peachy Turnons: String Manipulation
Posts
4,495
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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...
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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?
College Station, TX Preferred Nickname: Gig Current Mood: Just Peachy Turnons: String Manipulation
Posts
4,495
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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.
Last edited by gigemboy; Sep 17th, 2006 at 02:17 PM.
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
I am currently having trouble with trying to implement the code.
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
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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?
Code:
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)
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
Originally Posted by 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?
Code:
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)
where you have screenshotname, what about if you add the path you want to save the image to and then specify grpInfo.Text & ".jpg"
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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.
Code:
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.
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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.
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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:-(
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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:
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.
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
Code:
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'.
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
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.
Re: Easy Screen Capture Class - Capture Screen, Desktop Region, Form, or Controls
Originally Posted by 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.