If you can't find what you need using the site search on the toolbar above, or if you need more detailed help or just need to be pointed in the right direction, post your question to the newly opened kadaitcha.cx forums. Membership is free.

How to Interface to a Video Device and Capture Video and Images

Whilst not painlessly straightforward, interfacing to a webcam and capturing images is relatively easy. Image capture only requires you to load avicap32.dll and send messages into the device's window; the trick is in knowing what messages to send.

At the end of this article you will find a download for the source code an application that will interface into video devices and capture a video stream. The code also shows you how to save a captured bitmap image to a file on disk.

Walkthrough

Enumerating Devices

Device enumeration is important if you have more than one streaming video device or if you don't know what device number you want to connect to. Enumeration may not be needed for experimental code but it will be required if you don't intend to confuse and confound your users.

avicap32.dll exposes a method called capGetDriverDescription that can be used to obtain the names and versions of the installed capture devices. capGetDriverDescription takes four parameters, which consists of two buffer pointers and two size pointers. 128 bytes was chosen In the example below, but you can use any reasonable number for the buffers. If the device data won't fit into the buffers that you supply to to the method then the data will merely be truncated. You must also pre-fill the buffers to the correct size, and call the enumeration routine before exposing any functions to the user.

The code below enumerates capture devices and fills a ComboBox with device names. The device number directly corresponds to the item's index in the ComboBox so there is no need to create a list of device numbers:

' http://msdn.microsoft.com/en-us/library/ms708473.aspx
Declare Function capGetDriverDescriptionA Lib "avicap32.dll" ( _
                             ByVal
wDriver As Short, _
                             ByVal
lpszName As String, _
                             ByVal
cbName As Integer, _
                             ByVal
lpszVer As String, _
                             ByVal
cbVer As Integer) As Boolean

Private Sub EnumerateCaptureDevices()

    Dim
DeviceName As String = Space(128)    ' Device name buffer. 128 is a guesstimate.
    Dim DeviceVersion As String = Space(128) ' Device version buffer.
    Dim iDevice As Integer = 0               ' Device number, zero-based
    Dim bHaveDevice As Boolean

    Do
        bHaveDevice = capGetDriverDescriptionA(iDevice, DeviceName, 128, _
                                               DeviceVersion, 128)
        If bHaveDevice Then
            ' ComboBoxDevices is a DropDownList on the default form
            ComboBoxDevices.Items.Add(DeviceName.Trim)
        End If
        iDevice += 1
    Loop Until bHaveDevice = False

    If ComboBoxDevices.Items.Count <> 0 Then
        ComboBoxDevices.SelectedIndex = 0
        ButtonStart.Enabled = True
    Else
        ComboBoxDevices.Items.Add("No capture devices found")
    End If

End Sub   

Start Capture

To begin capturing output from the streaming video device, call capCreateCaptureWindow and pass the device number, window parameters and a handle to the display window. If the device is ready it will return a handle to its output window, at which point you connect to the driver, scale the output and set your desired preview rate. The PictureBox should display the video stream:

' http://msdn.microsoft.com/en-us/library/ms707853.aspx
Declare Function capCreateCaptureWindow Lib "avicap32.dll" Alias _
                       
 
"capCreateCaptureWindowA" (ByVal a As String, _
                                                    ByVal
b As Long, _
                                                   
ByVal
c As Integer, _
                                                   
ByVal
d As Integer, _
                                                   
ByVal
e As Integer, _
                                                   
ByVal
f As Integer, _
                                                   
ByVal
g As Long, _
                                                   
ByVal
h As Integer) As Long
'
' Window Styles
' http://msdn.microsoft.com/en-us/library/czada357(VS.80).aspx
Private Const WS_CHILD As Integer = &H40000000
Private Const WS_VISIBLE As Integer = &H10000000
'
' Windows User Interface Services
' http://msdn.microsoft.com/en-us/library/ms961540.aspx
Private Const SWP_NOMOVE As Short = &H2S
Private Const SWP_NOZORDER As Short = &H4S
Private Const HWND_BOTTOM As Short = 1
'
' Video capture messages
' http://msdn.microsoft.com/en-us/library/ms713480(VS.85).aspx

Private Const WM_CAP_DLG_VIDEOFORMAT As Integer = &H429
Private Const WM_CAP_DRIVER_CONNECT As Integer = &H40A
Private Const WM_CAP_DRIVER_DISCONNECT As Integer = &H40B
Private Const WM_CAP_EDIT_COPY As Integer = &H41E
Private Const WM_CAP_DRIVER_CONNECT As Integer = &H40A
Private Const WM_CAP_SET_PREVIEW As Integer = &H432
Private Const WM_CAP_SET_PREVIEWRATE As Integer = &H434
Private Const WM_CAP_SET_SCALE As Integer = &H435
'
' Preview window handle

Private hHwnd As Integer

Private Sub StartCapture()

    hHwnd = capCreateCaptureWindow(ComboBoxDevices.SelectedIndex, _
                                   WS_CHILD Or WS_VISIBLE, 0, 0, 320, 240, _
                                   PictureBoxCapture.Handle.ToInt32, 0)

    If (hHwnd <> 0) Then
        ' These calls to SendMessage return integer results but we are ignoring them.
        ' ComboBoxDevices is a DropDownList on the default form, populated by
        ' a call to EnumerateCaptureDevices
        Call SendMessage(hHwnd, WM_CAP_DRIVER_CONNECT, ComboBoxDevices.SelectedIndex, 0&)
        ' Scale
        Call SendMessage(hHwnd, WM_CAP_SET_SCALE, True, 0&)
        ' Preview rate in milliseconds
        Call SendMessage(hHwnd, WM_CAP_SET_PREVIEWRATE, 30&, 0&)
        ' Begin preview
        Call SendMessage(hHwnd, WM_CAP_SET_PREVIEW, 1&, 0&)
        ' PictureBoxCapture is a PictureBox on the default form
        ' Resize the device output window to fit inside PictureBoxCapture
        Call SetWindowPos(hHwnd, HWND_BOTTOM, 0%, 0%, PictureBoxCapture.Width, _
                          PictureBoxCapture.Height, SWP_NOMOVE Or SWP_NOZORDER)
    Else
        MsgBox("No capture devices found")
    End If

End Sub

Cleaning Up

Once the video stream is no longer needed, send a WM_CAP_DRIVER_DISCONNECT message to the device window then destroy the device window itself:

Private Sub Finished()

    ' Disconnect from the video stream
    SendMessage(hHwnd, WM_CAP_DRIVER_DISCONNECT, ComboBoxDevices.SelectedIndex, 0&)
    ' Destroy the output window
    DestroyWindow(hHwnd)
    ' Exit, close the default form
    Me.Close()

End Sub   

Download Sample Project

All code examples on this site have been developed for .Net Framework 3.5