oday, a webcam is a common peripheral, used most often for video conferencing, that most people can easily afford. But what can you do with your webcam besides video conferencing? If you are a developer, the answer is plenty; you will be glad to know that integrating a webcam with an application is not as difficult as you might imagine.Using the AVICap window class available in the Windows operating system, you can easily incorporate video capture capabilities into your Windows application. The uses of this functionality are endless but in particular you can easily populate employee and other person databases with mug shots taken directly from the users' terminal.
The AVICap class (located in the avicap32.dll file) contains message-based interfaces to access video and waveform-audio acquisition hardware and provides the ability to capture streaming video to disk. The only downside to the AVICap class is that it is an API and is thus not exposed as a managed class to the .NET developer. Hence, as a .NET developer you'll need to use Platform Invoke (P/Invoke) to make use of the API.
In this article, I will show you how to incorporate video capabilities into your .NET Windows applications. In particular, you will learn how to:
To show how to use the AVICap class for integrating video into your Windows application, I'll use Visual Studio 2005 to create a new Windows application project. I'll name the project C:\VideoCapture. The application that you will build will list all the video sources available on your computer. You can then select a video source (in this case, your webcam) and preview its content. You will also learn how to record a video stream to file.
First, populate the default Windows Form using the controls shown in Figure 1. You will need a ListBox control for displaying the video sources on your computer, a PictureBox control, with which to preview the video captures, and three Button controls to start and stop the video recording as well as to stop the selected camera.
Switch to the code-behind of the form and import the following namespace (required for P/Invoke):
After declaring the constants, you need to declare the functions. The first two functions are needed for video capturing purposes and can be found in the avicap32.dll library, while the next three functions (found in user32.dll) are used for manipulating the various windows.
Users can view a video source by selecting it in the ListBox control. To allow the user to do that, double-click on the ListBox control and code the following:
Note that the recording of video takes up large amount of disk space and can fill up your hard disk storage pretty quickly. Be sure to click the Stop Recording button to ensure that the file does not get too big. As an example, a 37-second clip took up 66MB of disk space (see Figure 4).
Using Video Capability in a Business Application
Now that I have managed to integrate video into my Windows application, I'll consider a practical use of it. In this section, I will use data-binding to display some records from the Employees table in the Northwind database (one of the sample databases that comes with SQL Server 2000).
If you are familiar with the Northwind database, you know that in the Employees table there is a field known as Photo. This field is used to store employees’ photographs. In a real-life application, it would be much easier to add in an employee’s photo if you can take a snapshot of him using a webcam and then directly add the record to the database. In this section, I will show you how to do that.
First, add a new data source to the project. You can do so using the Data->Add New Data Source… menu (see Figure 5).
The Data Source Configuration Wizard will appear. Choose Database as the data source and click Next. In the next window, click the New Connection… button to establish a connection to the Northwind database.Enter the name of the SQL Server containing the Northwind database. For my example, it is located on the same machine running Visual Studio 2005 and hence I entered "(local)." Select the Northwind database and then click OK (see Figure 6). Click Next when you are back to the previous window.
In the next window, you will choose the tables to use. Check the fields as shown in Figure 7. Click Finish to complete the process. The fields selected are: EmployeeID, LastName, FirstName, Title, and Photo. The Photo field is of the image data type, which contains images of employee. You will bind the Photo field to a PictureBox control on the windows form.
The Employees item will now appear in the Data Sources window (Data->Show Data Sources). Change the bindings of the Employees table as shown in Figure 8. Essentially, you want to view the Employees records in the detail view and bind the Photo field to a PictureBox control.The Employees table should now look like Figure 9.
Drag the Employees table from the Data Sources window and drop it onto Form1 (see Figure 10). You should see that a few controls are added automatically to the form. Resize the PictureBox control and set its SizeMode property to AutoSize.If you test the application now (by pressing F5), you will be able to view the records in the Employees table (see Figure 11.). You can add a record by clicking the Add New button, entering the value for each field, and then clicking the Save Data button to save the changes.
This is where things get interesting. When you add a new record, you would want to make use of the webcam to take a photo of the employee and then save the photo directly to the database. To do so, first add a Button control to the bottom of the PictureBox control and name it Capture Photo (see Figure 12).Double-click the Add New button so that when the user adds a new record, the video source is now bound to the PhotoPictureBox control:
That's it! Press F5 to test the application. When the form loads, click on the Add New button to add a new record. Enter the details as shown in Figure 13 and then position the webcam to take a nice snapshot of yourself. Smile and then click the Capture Photo button.Finally, click the Save Data button to save the new record onto the database. You can verify that the photo is saved by restarting the application and then viewing the records again.
In this article, you have seen how to use the AVICap class to integrate video into your Windows application. While I have only showed you one particular usage, there are in fact many uses for video: you can build a video surveillance system using the techniques described in this article or you can build your own video conferencing application. The possibilities are endless and please let me know if you have an innovative application built using the techniques described in this article.
The AVICap class (located in the avicap32.dll file) contains message-based interfaces to access video and waveform-audio acquisition hardware and provides the ability to capture streaming video to disk. The only downside to the AVICap class is that it is an API and is thus not exposed as a managed class to the .NET developer. Hence, as a .NET developer you'll need to use Platform Invoke (P/Invoke) to make use of the API.
In this article, I will show you how to incorporate video capabilities into your .NET Windows applications. In particular, you will learn how to:
- preview video input (within your Windows application) from your Webcam
- record streaming video
- capture images using your webcam.
To show how to use the AVICap class for integrating video into your Windows application, I'll use Visual Studio 2005 to create a new Windows application project. I'll name the project C:\VideoCapture. The application that you will build will list all the video sources available on your computer. You can then select a video source (in this case, your webcam) and preview its content. You will also learn how to record a video stream to file.
First, populate the default Windows Form using the controls shown in Figure 1. You will need a ListBox control for displaying the video sources on your computer, a PictureBox control, with which to preview the video captures, and three Button controls to start and stop the video recording as well as to stop the selected camera.
Figure 1. Proper Form: The screen shot shows the placement of each control you'll need to put on the default Windows Form in order to create the functionality for the sample application. |
Imports System.Runtime.InteropServices
Within the Form1 class, declare the constants used by the AVICap class:
Const WM_CAP_START = &H400S
Const WS_CHILD = &H40000000
Const WS_VISIBLE = &H10000000
Const WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10
Const WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11
Const WM_CAP_EDIT_COPY = WM_CAP_START + 30
Const WM_CAP_SEQUENCE = WM_CAP_START + 62
Const WM_CAP_FILE_SAVEAS = WM_CAP_START + 23
Const WM_CAP_SET_SCALE = WM_CAP_START + 53
Const WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52
Const WM_CAP_SET_PREVIEW = WM_CAP_START + 50
Const SWP_NOMOVE = &H2S
Const SWP_NOSIZE = 1
Const SWP_NOZORDER = &H4S
Const HWND_BOTTOM = 1
After declaring the constants, you need to declare the functions. The first two functions are needed for video capturing purposes and can be found in the avicap32.dll library, while the next three functions (found in user32.dll) are used for manipulating the various windows.
'--The capGetDriverDescription function retrieves the version
' description of the capture driver--
Declare Function capGetDriverDescriptionA Lib "avicap32.dll" _
(ByVal wDriverIndex As Short, _
ByVal lpszName As String, ByVal cbName As Integer, _
ByVal lpszVer As String, _
ByVal cbVer As Integer) As Boolean
'--The capCreateCaptureWindow function creates a capture window--
Declare Function capCreateCaptureWindowA Lib "avicap32.dll" _
(ByVal lpszWindowName As String, ByVal dwStyle As Integer, _
ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, _
ByVal nHeight As Short, ByVal hWnd As Integer, _
ByVal nID As Integer) As Integer
'--This function sends the specified message to a window or windows--
Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Integer, ByVal Msg As Integer, _
ByVal wParam As Integer, _
<MarshalAs(UnmanagedType.AsAny)> ByVal lParam As Object) As Integer
'--Sets the position of the window relative to the screen buffer--
Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" _
(ByVal hwnd As Integer, _
ByVal hWndInsertAfter As Integer, ByVal x As Integer, _
ByVal y As Integer, _
ByVal cx As Integer, ByVal cy As Integer, _
ByVal wFlags As Integer) As Integer
'--This function destroys the specified window--
Declare Function DestroyWindow Lib "user32" _
(ByVal hndw As Integer) As Boolean
Also declare the following member variables:
'---used to identify the video source---
Dim VideoSource As Integer
'---used as a window handle---
Dim hWnd As Integer
When the form is loaded for the first time, all the video sources connected to your computer will be listed in the ListBox control. This task is accomplished by the ListVideoSources() subroutine:
Private Sub Form1_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
btnStartRecording.Enabled = True
btnStopRecording.Enabled = False
'---list all the video sources---
ListVideoSources()
End Sub
The ListVideoSources() subroutine calls the capGetDriverDescriptionA() function and lists all the video sources in the ListBox control. Up to 10 video sources are supported:
'---list all the various video sources---
Private Sub ListVideoSources()
Dim DriverName As String = Space(80)
Dim DriverVersion As String = Space(80)
For i As Integer = 0 To 9
If capGetDriverDescriptionA(i, DriverName, 80, _
DriverVersion, 80) Then
lstVideoSources.Items.Add(DriverName.Trim)
End If
Next
End Sub
Figure 2 shows the ListBox control showing a video source connected to my computer when the form is loaded.Figure 2. Video Options: The ListBox control displays a list of the list of video sources from your computer. |
'---list all the video sources---
Private Sub lstVideoSources_SelectedIndexChanged( _
ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles lstVideoSources.SelectedIndexChanged
'---check which video source is selected---
VideoSource = lstVideoSources.SelectedIndex
'---preview the selected video source
PreviewVideo(PictureBox1)
End Sub
The previous event basically identifies the selected video source and then calls the PreviewVideo() subroutine to preview the video, which is shown below:
'---preview the selected video source---
Private Sub PreviewVideo(ByVal pbCtrl As PictureBox)
hWnd = capCreateCaptureWindowA(VideoSource, _
WS_VISIBLE Or WS_CHILD, 0, 0, 0, _
0, pbCtrl.Handle.ToInt32, 0)
If SendMessage( _
hWnd, WM_CAP_DRIVER_CONNECT, _
VideoSource, 0) Then
'---set the preview scale---
SendMessage(hWnd, WM_CAP_SET_SCALE, True, 0)
'---set the preview rate (ms)---
SendMessage(hWnd, WM_CAP_SET_PREVIEWRATE, 30, 0)
'---start previewing the image---
SendMessage(hWnd, WM_CAP_SET_PREVIEW, True, 0)
'---resize window to fit in PictureBox control---
SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, _
pbCtrl.Width, pbCtrl.Height, _
SWP_NOMOVE Or SWP_NOZORDER)
Else
'--error connecting to video source---
DestroyWindow(hWnd)
End If
End Sub
The Stop Camera button calls the StopPreviewWindow() subroutine to destroy the current window showing the video preview:
'---stop the preview window---
Private Sub btnStopCamera_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnStopCamera.Click
StopPreviewWindow()
End Sub
The StopPreviewWindow() subroutine is as follows:
'--disconnect from video source---
Private Sub StopPreviewWindow()
SendMessage(hWnd, WM_CAP_DRIVER_DISCONNECT, VideoSource, 0)
DestroyWindow(hWnd)
End Sub
The Start Recording button allows you to start capturing the selected video source:
'---Start recording the video---
Private Sub btnStartRecording_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnStartRecording.Click
btnStartRecording.Enabled = False
btnStopRecording.Enabled = True
'---start recording---
SendMessage(hWnd, WM_CAP_SEQUENCE, 0, 0)
End Sub
When the Stop Recording button is clicked, the video stream is saved as an .avi file:
'---stop recording and save it on file---
Private Sub btnStopRecording_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnStopRecording.Click
btnStartRecording.Enabled = True
btnStopRecording.Enabled = False
'---save the recording to file---
SendMessage(hWnd, WM_CAP_FILE_SAVEAS, 0, _
"C:\RecordedVideo.avi")
End Sub
That’s it! You can now test the application by pressing F5. Make sure you have a video source (e.g. webcam) connected to your computer. You should see an item in the ListBox control (see Figure 3). Click the video source and you should see an image shown up in the PictureBox control. To start recording, click the Start Recording button and then click the Stop Recording button to save the video to file. The Stop Camera will disconnect the selected video source from the PictureBox control.Note that the recording of video takes up large amount of disk space and can fill up your hard disk storage pretty quickly. Be sure to click the Stop Recording button to ensure that the file does not get too big. As an example, a 37-second clip took up 66MB of disk space (see Figure 4).
Using Video Capability in a Business Application
Now that I have managed to integrate video into my Windows application, I'll consider a practical use of it. In this section, I will use data-binding to display some records from the Employees table in the Northwind database (one of the sample databases that comes with SQL Server 2000).
If you are familiar with the Northwind database, you know that in the Employees table there is a field known as Photo. This field is used to store employees’ photographs. In a real-life application, it would be much easier to add in an employee’s photo if you can take a snapshot of him using a webcam and then directly add the record to the database. In this section, I will show you how to do that.
First, add a new data source to the project. You can do so using the Data->Add New Data Source… menu (see Figure 5).
The Data Source Configuration Wizard will appear. Choose Database as the data source and click Next. In the next window, click the New Connection… button to establish a connection to the Northwind database.Enter the name of the SQL Server containing the Northwind database. For my example, it is located on the same machine running Visual Studio 2005 and hence I entered "(local)." Select the Northwind database and then click OK (see Figure 6). Click Next when you are back to the previous window.
In the next window, you will choose the tables to use. Check the fields as shown in Figure 7. Click Finish to complete the process. The fields selected are: EmployeeID, LastName, FirstName, Title, and Photo. The Photo field is of the image data type, which contains images of employee. You will bind the Photo field to a PictureBox control on the windows form.
The Employees item will now appear in the Data Sources window (Data->Show Data Sources). Change the bindings of the Employees table as shown in Figure 8. Essentially, you want to view the Employees records in the detail view and bind the Photo field to a PictureBox control.The Employees table should now look like Figure 9.
Drag the Employees table from the Data Sources window and drop it onto Form1 (see Figure 10). You should see that a few controls are added automatically to the form. Resize the PictureBox control and set its SizeMode property to AutoSize.If you test the application now (by pressing F5), you will be able to view the records in the Employees table (see Figure 11.). You can add a record by clicking the Add New button, entering the value for each field, and then clicking the Save Data button to save the changes.
This is where things get interesting. When you add a new record, you would want to make use of the webcam to take a photo of the employee and then save the photo directly to the database. To do so, first add a Button control to the bottom of the PictureBox control and name it Capture Photo (see Figure 12).Double-click the Add New button so that when the user adds a new record, the video source is now bound to the PhotoPictureBox control:
Private Sub BindingNavigatorAddNewItem_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles BindingNavigatorAddNewItem.Click
StopPreviewWindow()
PreviewVideo(PhotoPictureBox)
End Sub
When the user clicks on the Capture Photo button, you will call the CaptureImage subroutine to freeze the photo:
Private Sub btnCapturePhoto_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnCapturePhoto.Click
CaptureImage()
End Sub
The CaptureImage() subroutine copies the image from the video source onto the clipboard. You then display the image using the PhotoPictureBox control:
'---save the image---
Private Sub CaptureImage()
Dim data As IDataObject
Dim bmap As Image
'---copy the image to the clipboard---
SendMessage(hWnd, WM_CAP_EDIT_COPY, 0, 0)
'---retrieve the image from clipboard and convert it
' to the bitmap format
data = Clipboard.GetDataObject()
If data.GetDataPresent(GetType(System.Drawing.Bitmap)) Then
bmap = _
CType(data.GetData(GetType(System.Drawing.Bitmap)), _
Image)
PhotoPictureBox.Image = bmap
StopPreviewWindow()
End If
End Sub
Figure 13. Adding the Author: In this screen shot I'm taking a photo of myself to create a new record in the employee database. |
In this article, you have seen how to use the AVICap class to integrate video into your Windows application. While I have only showed you one particular usage, there are in fact many uses for video: you can build a video surveillance system using the techniques described in this article or you can build your own video conferencing application. The possibilities are endless and please let me know if you have an innovative application built using the techniques described in this article.
Wei-Meng Lee (Microsoft .NET MVP) is a technologist and founder of Developer Learning Solutions, a technology company specializing in hands-on training on the latest Microsoft technologies. He speaks regularly at international conferences and has authored and co-authored numerous books on .NET, XML, and wireless technologies, including 'Windows XP Unwired' and the '.NET Compact Framework Pocket Guide' (both from O'Reilly Media, Inc). He writes extensively for the O'Reilly Network on topics ranging from .NET to Mac OS X. Wei-Meng is currently the Microsoft Regional Director for Singapore.
Download the Code for this Article