Capture WebCam with WinForms2

I was asked whether it is possible to capture a webcam's output in Windows
Forms 2.0 so I did a bit researching.

First I thought I would have to do this in DirectX but then I found some API
calls for VB6 and translated them to VB .NET 2.

In fact it is very easy to capture the output. You simply need a Control and
it's handle.

I chose a PictureBox named PictureBox1 to do so.

You have to define the Win32 API calls first. We will need two API functions
SendMessage and capCreateCaptureWindow.

Private Declare Auto Function SendMessage Lib "user32" (ByVal hwnd As
IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As
Integer) As Integer

Const EM_LINEFROMCHAR As Integer = &HC9
Const EM_LINEINDEX As Integer = &HBB

Private Declare Auto Function capCreateCaptureWindow 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
Integer, ByVal hWndParent As IntPtr, ByVal nID As Integer) As IntPtr

Private Const WS_CHILD As Integer = &H40000000
Private Const WS_VISIBLE As Integer = &H10000000
Private Const WM_USER As Short = &H400S
Private Const WM_CAP_START As Short = &H400S
Private Const WM_CAP_EDIT_COPY As Integer = (WM_CAP_START + 30)
Private Const WM_CAP_DRIVER_CONNECT As Integer = (WM_CAP_START + 10)
Private Const WM_CAP_SET_PREVIEWRATE As Integer = (WM_CAP_START + 52)
Private Const WM_CAP_SET_OVERLAY As Integer = (WM_CAP_START + 51)
Private Const WM_CAP_SET_PREVIEW As Integer = (WM_CAP_START + 50)
Private Const WM_CAP_DRIVER_DISCONNECT As Integer = (WM_CAP_START + 11)

Now we have to create the Wrappers to make API calls more comfortable:


''' <summary>
''' Keeps a Handle for our WebCam.
''' </summary>
Dim videoHandle As System.IntPtr

''' <summary>
''' Sends a preview of our WebCam output to then control obtaining
hWndParent.
''' </summary>
Public Function CreateCaptureWindow(ByRef hWndParent As IntPtr, Optional
ByRef x As Integer = 0, Optional ByRef y As Integer = 0, Optional ByRef
nWidth As Integer = 320, Optional ByRef nHeight As Integer = 240, Optional
ByRef nCameraID As Integer = 0) As IntPtr
Dim previewHandle As IntPtr

previewHandle = capCreateCaptureWindow("Video", WS_CHILD +
WS_VISIBLE, x, y, nWidth, nHeight, hWndParent, 1)

SendMessage(previewHandle, WM_CAP_DRIVER_CONNECT, nCameraID, 0)
SendMessage(previewHandle, WM_CAP_SET_PREVIEWRATE, 30, 0)
SendMessage(previewHandle, WM_CAP_SET_OVERLAY, 1, 0)
SendMessage(previewHandle, WM_CAP_SET_PREVIEW, 1, 0)

Return previewHandle
End Function

''' <summary>
''' Captures the current output of our WebCam as a System.Drawing.Image.
''' </summary>
Public Function CapturePicture(ByRef nCaptureHandle As IntPtr) As
System.Drawing.Image
My.Computer.Clipboard.Clear()
SendMessage(nCaptureHandle, WM_CAP_EDIT_COPY, 0, 0)
Return My.Computer.Clipboard.GetImage
End Function

''' <summary>
''' Disconnects from the WebCam.
''' </summary>
''' <remarks>We need to call this on closing!</remarks>
Public Sub Disconnect(ByRef nCaptureHandle As IntPtr, Optional ByRef
nCameraID As Integer = 0)
SendMessage(nCaptureHandle, WM_CAP_DRIVER_DISCONNECT, nCameraID, 0)
End Sub

Now let's try to connect to the camera.


Private Sub Form1_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
videoHandle = Me.CreateCaptureWindow(Me.PictureBox1.Handle)
End Sub
End Class

Last but not least we have to do a CleanUp!>


Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As
System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Me.Disconnect(videoHandle)
End Sub

Comments

Popular posts from this blog

Custom Chrome in WPF

WPF: Binding updates