You want to capture a copy of the screen for processing in your Visual Basic 2005 application as a bitmap image, without resorting to any external applications.
Sample code folder: Chapter 10 \CaptureScreen
Use the GetScreen() function in the ScreenGrab module presented in this recipe.
There's no straightforward way to grab the contents of the screen using only functionality within the .NET Framework, but it is easy to call the appropriate Windows API functions to get the job done. The ScreenGrab module shown here wraps all the required function declarations and calls in an easy-to-use package.
Create a new Windows Forms application. Add a new module to the project named ScreenGrab.vb, and use the following code for its definition:
Module ScreenGrab 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 IntPtr Private Declare Function CreateCompatibleDC _ Lib "GDI32" (ByVal hDC As IntPtr) As IntPtr Private Declare Function CreateCompatibleBitmap _ Lib "GDI32" ( _ ByVal hDC As IntPtr, _ ByVal nWidth As Integer, _ ByVal nHeight As Integer _ ) As IntPtr Private Declare Function SelectObject _ Lib "GDI32" ( _ ByVal hDC As IntPtr, _ ByVal hObject As IntPtr _ ) As IntPtr Private Declare Function BitBlt _ Lib "GDI32" ( _ ByVal srchDC As IntPtr, _ ByVal srcX As Integer, _ ByVal srcY As Integer, _ ByVal srcW As Integer, _ ByVal srcH As Integer, _ ByVal desthDC As IntPtr, _ ByVal destX As Integer, _ ByVal destY As Integer, _ ByVal op As Integer _ ) As Integer Private Declare Function DeleteDC _ Lib "GDI32" (ByVal hDC As IntPtr) As Integer Private Declare Function DeleteObject _ Lib "GDI32" (ByVal hObj As IntPtr) As Integer Const SRCCOPY As Integer = &HCC0020 Public Function GetScreen( ) As Bitmap ' ----- Take a picture of the screen. Dim screenHandle As IntPtr Dim canvasHandle As IntPtr Dim screenBitmap As IntPtr Dim previousObject As IntPtr Dim resultCode As Integer Dim screenShot As Bitmap ' ----- Get a reference to the display. screenHandle = CreateDC("DISPLAY", "", "", "") ' ----- Make a canvas that is just like the ' display's canvas. canvasHandle = CreateCompatibleDC(screenHandle) ' ----- Create a bitmap that will hold the screen image. screenBitmap = CreateCompatibleBitmap(screenHandle, _ Screen.PrimaryScreen.Bounds.Width, _ Screen.PrimaryScreen.Bounds.Height) ' ----- Copy the screen image to the canvas/bitmap. previousObject = SelectObject(canvasHandle, _ screenBitmap) resultCode = BitBlt(canvasHandle, 0, 0, _ Screen.PrimaryScreen.Bounds.Width, _ Screen.PrimaryScreen.Bounds.Height, _ screenHandle, 0, 0, SRCCOPY) screenBitmap = SelectObject(canvasHandle, _ previousObject) ' ----- Finished with the canvases. resultCode = DeleteDC(screenHandle) resultCode = DeleteDC(canvasHandle) ' ----- Copy image to a .NET bitmap. screenShot = Image.FromHbitmap(screenBitmap) DeleteObject(screenBitmap) ' ----- Finished. Return screenShot End Function End Module
Now return to Form1, and add a Button control named ActCapture. Set its Text property to Capture Now. Next, add a CheckBox control named IncludeThisForm, set its Checked property to true, and set its Text property to Include This Form. Finally, add a PictureBox control named ScreenSummary, set its SizeMode property to StretchImage, and set its Size property to 200,150. Figure 10-23 shows the form and its controls.
Figure 10-23. The controls on the screen capture sample
Add the following code to Form1's class template:
Private Sub ActCapture_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles ActCapture.Click ' ----- Copy the screen. ScreenSummary.Image = GetScreen( ) End Sub Private Sub IncludeThisForm_CheckedChanged( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles IncludeThisForm.CheckedChanged ' ----- Adjust the opacity as needed. If (IncludeThisForm.Checked = True) Then Me.Opacity = 1.0 Else Me.Opacity = 0.99 End If End Sub
It turns out that the standard method of copying the screen ignores semitransparent forms, so setting the form's opacity to anything below 1.0 makes it invisible to the screen capture process.
Run the program, and click the ActCapture button. Figure 10-24 shows the form in use.
Figure 10-24. A capture of the entire screen with Visual Studio prominently displayed
Details of the API functions included in the ScreenGrab module and their use are beyond the scope of this book, but there are plenty of resources on the Internet if you want to find out how they work.