'Author: Arman Ghazanchyan 'Created date: 11/02/2006 'Last updated: 08/05/2008 Imports System Imports System.Drawing Imports System.ComponentModel Imports System.Runtime.InteropServices ''' ''' Provides shared methods for capturing images from the screen. ''' _ Public NotInheritable Class SCapture #Region " Methods " _ Private Sub New() End Sub ''' ''' Captures the bitmap of the entire screen (all monitors). ''' Returns a bitmap if the function succeeds, ''' otherwise throws a SCaptureException. ''' ''' A value that specifies if the ''' cursor should be included in the captured bitmap. _ Public Shared Function FullScreen(ByVal includeCursor As Boolean) As Bitmap 'Capture and return the full screen (all monitors) rectangle image. Return SCapture.ScreenRectangle(SystemInformation.VirtualScreen, includeCursor) End Function ''' ''' Captures the bitmap of the specified display device. ''' Returns a bitmap if the function succeeds, ''' otherwise throws a SCaptureException. ''' ''' A diplay device. ''' A value that specifies if the ''' cursor should be included in the captured bitmap. _ Public Shared Function DisplayMonitor(ByVal monitor As System.Windows.Forms.Screen, ByVal includeCursor As Boolean) As Bitmap If monitor IsNot Nothing Then 'Capture and return the display monitor rectangle bitmap. Return SCapture.ScreenRectangle(monitor.Bounds, includeCursor) Else 'The screen object is nothing, throw an SCaptureException. Throw New SCaptureException("The monitor cannot be Null (Nothing in VB).") End If End Function ''' ''' Captures the bitmap of an active window from the screen. Returns ''' a bitmap if the function succeeds, otherwise throws a SCaptureException. ''' ''' A value that specifies if the ''' cursor should be included in the captured bitmap. _ Public Shared Function ActiveWindow(ByVal includeCursor As Boolean) As Bitmap Dim hwnd As IntPtr 'Get the handle of the active window on the desktop. hwnd = NativeMethods.GetForegroundWindow() If hwnd <> IntPtr.Zero Then 'Capture and return the active window bitmap. Return SCapture.Control(hwnd, includeCursor) Else 'The active window could not be found, throw an SCaptureException. Throw New SCaptureException("Could not find any active window.") End If End Function ''' ''' Captures the bitmap of a window from the screen. ''' Returns a bitmap if the function succeeds, otherwise throws a SCaptureException. ''' ''' A point within the window in the screen coordinates. ''' A value that specifies if the ''' cursor should be included in the captured bitmap. _ Public Overloads Shared Function Window(ByVal p As Point, ByVal includeCursor As Boolean) As Bitmap 'Get the handle of a window at the point. Dim hwnd As IntPtr = NativeMethods.WindowFromPoint(p) If hwnd <> IntPtr.Zero Then 'Get the ancestor window of this window. Dim hpwnd As IntPtr = NativeMethods.GetAncestor(hwnd, NativeMethods.GA_ROOTOWNER) If hpwnd <> IntPtr.Zero Then 'Capture and return the window bitmap. Return SCapture.Control(hpwnd, includeCursor) Else 'There is no ancestor window or the window is the ancestor. 'So return the existing window bitmap. Return SCapture.Control(hwnd, includeCursor) End If Else 'There is no window at the specified point, throw an SCaptureException. Throw New SCaptureException("Could not find any window at the specified point.") End If End Function ''' ''' Captures the bitmap of a window from the screen specified by a handle. ''' Returns a bitmap if the function succeeds, otherwise throws a SCaptureException. ''' ''' The handle to a window whose ''' bitmap should be captured. ''' A value that specifies if the ''' cursor should be included in the captured bitmap. _ Public Overloads Shared Function Window(ByVal hwnd As IntPtr, ByVal includeCursor As Boolean) As Bitmap If hwnd <> IntPtr.Zero Then 'Capture and return the window bitmap. Return SCapture.Control(hwnd, includeCursor) Else 'The window handle is invalid, throw an SCaptureException. Throw New SCaptureException("Invalid window handle.") End If End Function ''' ''' Captures the bitmap of a control. ''' Returns a bitmap if the function succeeds, ''' otherwise throws a SCaptureException. ''' ''' A point within the control in the screen coordinates. ''' A value that specifies if the ''' cursor should be included in the captured bitmap. _ Public Overloads Shared Function Control(ByVal p As Point, ByVal includeCursor As Boolean) As Bitmap Dim hwnd As IntPtr 'Get the handle of a window at the point. hwnd = NativeMethods.WindowFromPoint(p) If hwnd <> IntPtr.Zero Then 'Capture and return the control bitmap. Return SCapture.Control(hwnd, includeCursor) Else 'There is no window/control at the specified point, throw an SCaptureException. Throw New SCaptureException("Could not find any control at the specified point.") End If End Function ''' ''' Captures the bitmap of a control. ''' Returns a bitmap if the function succeeds, ''' otherwise throws a SCaptureException. ''' ''' The handle of a control whose ''' bitmap should be captured. ''' A value that specifies if the ''' cursor should be included in the captured bitmap. _ Public Overloads Shared Function Control(ByVal hwnd As IntPtr, ByVal includeCursor As Boolean) As Bitmap Dim wRect As SCapture.Rect If hwnd <> IntPtr.Zero Then 'Get the window rectangle. If Not NativeMethods.GetWindowRect(hwnd, wRect) Then Dim eCode As Integer = Marshal.GetLastWin32Error 'The GetWindowRect Api method failed, throw an SCaptureException. Throw New SCaptureException(New Win32Exception(eCode).Message) Else 'Capture and return the control rectangle bitmap. Return SCapture.ScreenRectangle(wRect.ToRectangle, includeCursor) End If Else 'The control handle is invalid, throw an SCaptureException. Throw New SCaptureException("Invalid control handle.") End If End Function ''' ''' Captures the rectangle bitmap from the screen. ''' Returns a bitmap if the function succeeds, ''' otherwise throws a SCaptureException. ''' ''' A rectangle within the screen ''' coordinates whose bitmap should be captured. ''' A value that specifies if the ''' cursor should be included in the captured bitmap. _ Public Shared Function ScreenRectangle(ByVal rect As Rectangle, ByVal includeCursor As Boolean) As Bitmap If Not rect.IsEmpty AndAlso rect.Width <> 0 AndAlso rect.Height <> 0 Then Dim bmp As Bitmap = SCapture.GetImage(rect) If includeCursor Then 'Draw the cursor over the captured bitmap. SCapture.DrawCursor(rect, bmp) End If Return bmp Else 'The rectangle is empty, throw an SCaptureException. Throw New SCaptureException("Empty rectangle.") End If End Function ''' ''' Gets the bitmap of a screen rectangle area. ''' Returns a bitmap if the function succeeds, ''' otherwise throws a SCaptureException. ''' ''' A rectangle within the screen ''' coordinates whose bitmap should be captured. _ Private Shared Function GetImage(ByVal rect As Rectangle) As Bitmap Dim wHdc As IntPtr = SCapture.GetDC 'Create graphics object from bitmap. Dim g As Graphics Dim bmp As New Bitmap(rect.Width, rect.Height) g = Graphics.FromImage(bmp) 'Get the handle of the bitmap graphics object. Dim gHdc As IntPtr = g.GetHdc() 'Copy the screen rectangle to the bitmap. If Not NativeMethods.BitBlt(gHdc, 0, 0, rect.Width, rect.Height, _ wHdc, rect.X, rect.Y, NativeMethods.SRCCOPY Or NativeMethods.CAPTUREBLT) Then Dim eCode As Integer = Marshal.GetLastWin32Error g.ReleaseHdc(gHdc) g.Dispose() 'The BitBlt Api method failed, throw an SCaptureException. Throw New SCaptureException(New Win32Exception(eCode).Message) End If 'Release the handles to device contexts. g.ReleaseHdc(gHdc) NativeMethods.ReleaseDC(IntPtr.Zero, wHdc) g.Dispose() 'Return the captured bitmap. Return bmp End Function ''' ''' Get the handle device context for the entire screen. ''' _ Private Shared Function GetDC() As IntPtr 'Get the handle of the desktop device context. Dim wHdc As IntPtr = NativeMethods.GetDC(IntPtr.Zero) If wHdc = IntPtr.Zero Then Dim eCode As Integer = Marshal.GetLastWin32Error 'The GetDC Api method failed, throw an SCaptureException. Throw New SCaptureException(New Win32Exception(eCode).Message) Else Return wHdc End If End Function ''' ''' Draws the cursor onto the specified bitmap. ''' ''' A rectangle within the screen ''' coordinates whose bitmap is be captured. ''' An bitmap on which the cursor should be drawn. _ Private Shared Sub DrawCursor(ByVal rect As Rectangle, ByVal bmp As Bitmap) 'Get the cursor information. Dim cInfo As SCapture.CursorInfo = SCapture.GetCursorInfo If cInfo.flags = NativeMethods.CURSOR_SHOWING AndAlso rect.Contains(cInfo.ptScreenPos) Then 'Get the handle of the coursor icon. Dim hicon As IntPtr = SCapture.GetCursorIcon(cInfo.hCursor) 'Get the coursor icon information. Dim iInfo As SCapture.IconInfo = SCapture.GetIconInfo(hicon) Dim g As Graphics = Graphics.FromImage(bmp) 'Draw the coursor over the image. g.DrawIcon(Icon.FromHandle(hicon), cInfo.ptScreenPos.X - rect.X - iInfo.xHotspot, _ cInfo.ptScreenPos.Y - rect.Y - iInfo.yHotspot) g.Dispose() End If End Sub ''' ''' Retrieves the cursor icon. ''' ''' A cursor handle whose icon should be retrieved. _ Private Shared Function GetCursorIcon(ByVal hCursor As IntPtr) As IntPtr 'Get the handle of the coursor icon. Dim hicon As IntPtr = NativeMethods.CopyIcon(hCursor) If hicon = IntPtr.Zero Then Dim eCode As Integer = Marshal.GetLastWin32Error 'The CopyIcon Api method failed, throw an SCaptureException. Throw New SCaptureException(New Win32Exception(eCode).Message) Else 'Return the handle of the cursor icon. Return hicon End If End Function ''' ''' Retrieves the cursor information. ''' _ Private Shared Function GetCursorInfo() As SCapture.CursorInfo Dim cInfo As New SCapture.CursorInfo cInfo.cbSize = Marshal.SizeOf(cInfo) 'Get the coursor information. If Not NativeMethods.GetCursorInfo(cInfo) Then Dim eCode As Integer = Marshal.GetLastWin32Error 'The GetCursorInfo Api method failed, throw an SCaptureException. Throw New SCaptureException(New Win32Exception(eCode).Message) Else 'Return the coursor information. Return cInfo End If End Function ''' ''' Retrieves the cursor's icon information. ''' ''' An icon handle whose information should be retrieved. _ Private Shared Function GetIconInfo(ByVal hicon As IntPtr) As SCapture.IconInfo Dim iInfo As New SCapture.IconInfo 'Get the icon information. If Not NativeMethods.GetIconInfo(hicon, iInfo) Then Dim eCode As Integer = Marshal.GetLastWin32Error 'The GetIconInfo Api method failed, throw an SCaptureException. Throw New SCaptureException(New Win32Exception(eCode).Message) Else 'Return the icon information. Return iInfo End If End Function #End Region #Region " NativeMethods " ''' ''' Represents win32 Api shared methods, structures, and constants. ''' _ Private NotInheritable Class NativeMethods #Region " Constants " '============== GDI32 CONSTANTS =============== Public Const CAPTUREBLT As Int32 = &H40000000 Public Const BLACKNESS As Int32 = &H42 Public Const DSTINVERT As Int32 = &H550009 Public Const MERGECOPY As Int32 = &HC000CA Public Const MERGEPAINT As Int32 = &HBB0226 Public Const NOTSRCCOPY As Int32 = &H330008 Public Const NOTSRCERASE As Int32 = &H1100A6 Public Const PATCOPY As Int32 = &HF00021 Public Const PATINVERT As Int32 = &H5A0049 Public Const PATPAINT As Int32 = &HFB0A09 Public Const SRCAND As Int32 = &H8800C6 Public Const SRCCOPY As Int32 = &HCC0020 Public Const SRCERASE As Int32 = &H440328 Public Const SRCINVERT As Int32 = &H660046 Public Const SRCPAINT As Int32 = &HEE0086 Public Const WHITENESS As Int32 = &HFF0062 Public Const HORZRES As Int32 = 8 Public Const VERTRES As Int32 = 10 '=========================================== Public Const GA_PARENT As Int32 = 1 Public Const GA_ROOT As Int32 = 2 Public Const GA_ROOTOWNER As Int32 = 3 ''' ''' Represents the cursor showing constant. Used with CURSORINFO structure. ''' Public Const CURSOR_SHOWING As Integer = &H1 #End Region _ Private Sub New() End Sub _ Public Shared Function GetWindowRect( _ ByVal hWnd As IntPtr, _ ByRef lpRect As Rect) As Boolean End Function _ Public Shared Function ReleaseDC( _ ByVal hWnd As IntPtr, _ ByVal hdc As IntPtr) As Int32 End Function _ Public Shared Function WindowFromPoint( _ ByVal pt As Point) As IntPtr End Function _ Public Shared Function GetForegroundWindow() As IntPtr End Function _ Public Shared Function GetAncestor( _ ByVal hwnd As IntPtr, _ ByVal gaFlags As Int32) As IntPtr End Function _ Public Shared Function GetDC( _ ByVal hwnd As IntPtr) As IntPtr End Function _ Public Shared Function CopyIcon( _ ByVal hIcon As IntPtr) As IntPtr End Function _ Public Shared Function GetCursorInfo( _ ByRef pci As CursorInfo) As Boolean End Function _ Public Shared Function GetIconInfo( _ ByVal hIcon As IntPtr, _ ByRef piconinfo As IconInfo) As Boolean End Function _ Public Shared Function BitBlt( _ ByVal hdcDest As IntPtr, _ ByVal nXDest As Int32, _ ByVal nYDest As Int32, _ ByVal nWidth As Int32, _ ByVal nHeight As Int32, _ ByVal hdcSrc As IntPtr, _ ByVal nXSrc As Int32, _ ByVal nYSrc As Int32, _ ByVal dwRop As Int32) As Boolean End Function End Class #End Region #Region " Structures " _ Private Structure Rect Public Left As Int32 Public Top As Int32 Public Right As Int32 Public Bottom As Int32 ''' ''' Converts the ICapture.Rect object to System.Drawing.Rectangle object. ''' _ Public Function ToRectangle() As Rectangle Return New Rectangle(Me.Left, Me.Top, Me.Right - Me.Left, Me.Bottom - Me.Top) End Function End Structure _ Private Structure CursorInfo Public cbSize As Int32 Public flags As Int32 Public hCursor As IntPtr Public ptScreenPos As Point End Structure _ Private Structure IconInfo Public fIcon As Boolean Public xHotspot As Int32 Public yHotspot As Int32 Public hbmMask As IntPtr Public hbmColor As IntPtr End Structure #End Region End Class #Region " SCaptureException " _ Public Class SCaptureException Inherits Exception _ Sub New() End Sub _ Public Sub New(ByVal message As String) MyBase.New(message) End Sub _ Public Sub New(ByVal message As String, ByVal ex As Exception) MyBase.New(message, ex) End Sub _ Protected Sub New(ByVal info As Runtime.Serialization.SerializationInfo, ByVal context As Runtime.Serialization.StreamingContext) MyBase.New(info, context) End Sub End Class #End Region